From 6206c36e4e794cf1ce097a1c97e240443b705d83 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Wed, 3 Dec 2025 14:58:57 -0500 Subject: [PATCH 1/6] Add comprehensive NatSpec documentation to all contracts Adds detailed NatSpec documentation including @title, @notice, @dev, @param, and @return tags to all Solidity files in the project (interfaces, implementation, examples, tests, and scripts). Improves code clarity and developer experience for consuming the OpacitySDK. --- foundry.lock | 8 ++ script/Deploy.s.sol | 36 +++++- src/IOpacitySDK.sol | 127 ++++++++++++++------ src/OpacitySDK.sol | 79 +++++++++--- src/examples/SimpleVerificationConsumer.sol | 30 ++++- src/examples/StorageQueryConsumer.sol | 95 +++++++++++---- test/ExampleConsumers.t.sol | 47 +++++++- test/OpacitySDK.t.sol | 71 ++++++++++- 8 files changed, 400 insertions(+), 93 deletions(-) create mode 100644 foundry.lock diff --git a/foundry.lock b/foundry.lock new file mode 100644 index 0000000..3dc4ee9 --- /dev/null +++ b/foundry.lock @@ -0,0 +1,8 @@ +{ + "lib/eigenlayer-middleware": { + "rev": "f5adbcac55d9336cd646ce71bc467aa7e20f1a12" + }, + "lib/forge-std": { + "rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505" + } +} \ No newline at end of file diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 0b0f6ae..761b547 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -8,17 +8,38 @@ import "../src/examples/SimpleVerificationConsumer.sol"; /** * @title Deploy - * @notice Main deployment script for OpacitySDK contracts + * @notice Foundry deployment script for OpacitySDK example contracts + * @dev This script deploys the SimpleVerificationConsumer contract using an existing + * BLS signature checker. It requires: + * - PRIVATE_KEY environment variable set with the deployer's private key + * - A deployed BLS signature checker address + * - A deployed registry coordinator address + * + * Usage: + * ```bash + * forge script script/Deploy.s.sol:Deploy \ + * --sig "run(address,address)" \ + * --rpc-url $RPC_URL --broadcast + * ``` */ contract Deploy is Script { - // Deployed contracts + /** + * @notice Reference to the BLS signature checker contract + */ BLSSignatureChecker public blsSignatureChecker; + + /** + * @notice The deployed SimpleVerificationConsumer instance + */ SimpleVerificationConsumer public simpleVerificationConsumer; /** - * @notice Deploy SimpleVerificationConsumer - * @param blsSignatureCheckerAddress BLS signature checker address - * @param registryCoordinator Registry coordinator address + * @notice Main deployment entrypoint + * @dev Deploys a SimpleVerificationConsumer linked to the provided BLS signature checker. + * Reads PRIVATE_KEY from environment variables for transaction signing. + * Logs deployment progress and final addresses to console. + * @param blsSignatureCheckerAddress Address of an already-deployed BLS signature checker (must be non-zero) + * @param registryCoordinator Address of the EigenLayer registry coordinator (must be non-zero, used for logging) */ function run(address blsSignatureCheckerAddress, address registryCoordinator) external { require(blsSignatureCheckerAddress != address(0), "Invalid BLS address"); @@ -45,7 +66,10 @@ contract Deploy is Script { } /** - * @notice Print deployment summary + * @notice Prints a summary of all deployed contracts and verifies linkage + * @dev Internal helper function called after deployment completes. + * Verifies that the SimpleVerificationConsumer is correctly linked + * to the BLS signature checker by comparing stored addresses. */ function printDeploymentSummary() internal view { console.log("\n========================================"); diff --git a/src/IOpacitySDK.sol b/src/IOpacitySDK.sol index 3d01bb1..aed703d 100644 --- a/src/IOpacitySDK.sol +++ b/src/IOpacitySDK.sol @@ -5,14 +5,20 @@ import {IBLSSignatureCheckerTypes} from "@eigenlayer-middleware/interfaces/IBLSS /** * @title IOpacitySDK - * @notice Interface for OpacitySDK containing all structs, events, and errors + * @notice Interface for the Opacity SDK, providing verifiable private data attestations on-chain + * @dev This interface defines all structs, events, errors, and function signatures for the OpacitySDK. + * The SDK enables verification of BLS-signed commitments from an operator network, allowing + * smart contracts to validate private data attestations without exposing the underlying data. */ interface IOpacitySDK { /** * @notice Resource tuple (PU, r, PA) representing a resource from a platform - * @param platformUrl Platform URL (e.g., "https://api.bank.com") - * @param resourceName Resource name (e.g., "balance") - * @param param Resource-specific parameter (e.g., "A1") + * @dev Resources are the fundamental building blocks of the Opacity protocol, representing + * data fetched from external platforms. Each resource is uniquely identified by the + * combination of platform URL, resource name, and parameter. + * @param platformUrl The base URL of the platform API (e.g., "https://api.bank.com") + * @param resourceName The name of the resource endpoint (e.g., "balance") + * @param param A resource-specific parameter for the query (e.g., account ID "A1") */ struct Resource { string platformUrl; @@ -21,9 +27,12 @@ interface IOpacitySDK { } /** - * @notice Public reveal pair (Resource, value) + * @notice Public reveal pair (Resource, value) for publicly committed data + * @dev ValueReveal structures contain data that the user has chosen to reveal publicly + * as part of their attestation. Values are always encoded as strings regardless + * of their underlying type (numbers, booleans, etc.). * @param resource The resource being revealed - * @param value The primitive value (string, number as string, bool as string, or bytes) + * @param value The revealed value encoded as a string (e.g., "730.25", "true", "Acme Inc") */ struct ValueReveal { Resource resource; @@ -31,9 +40,13 @@ interface IOpacitySDK { } /** - * @notice Composition operation - * @param op Operation type: "sum" or "concat" - * @param resources Array of resources to apply the operation to + * @notice Composition operation for combining multiple resource values + * @dev Compositions allow aggregating multiple resources into a single derived value. + * Supported operations: + * - "sum": Adds numeric values from all resources together + * - "concat": Concatenates string values from all resources + * @param op The operation type to perform ("sum" or "concat") + * @param resources Array of resources whose values will be combined by the operation */ struct Composition { string op; @@ -41,9 +54,13 @@ interface IOpacitySDK { } /** - * @notice Conditional atom for conditions - * @param atomType Type of condition: "substr" or "gt" - * @param value The value for the condition (needle for substr, threshold for gt) + * @notice Conditional atom representing a single condition check + * @dev CondAtom structures define individual conditions that can be applied to resources. + * Supported condition types: + * - "substr": Checks if the resource value contains the specified substring + * - "gt": Checks if the numeric resource value is greater than the threshold + * @param atomType The type of condition to evaluate ("substr" or "gt") + * @param value The condition parameter (substring to find, or numeric threshold as string) */ struct CondAtom { string atomType; @@ -51,9 +68,12 @@ interface IOpacitySDK { } /** - * @notice Condition group - * @param targets Array of resources that must satisfy all conditions - * @param allOf Array of conditional atoms that all targets must satisfy + * @notice Condition group representing a set of conditions applied to target resources + * @dev A ConditionGroup defines that ALL specified conditions (allOf) must be satisfied + * by ALL specified target resources. This enables complex validation logic such as + * "both account balances must be greater than $100" or "employer name must contain 'Inc'". + * @param targets Array of resources that must all satisfy the conditions + * @param allOf Array of conditional atoms that all targets must satisfy (AND logic) */ struct ConditionGroup { Resource[] targets; @@ -61,12 +81,16 @@ interface IOpacitySDK { } /** - * @notice Unified Commitment Payload (P) as defined in the schema - * @param userAddr Signer's address - * @param values Optional public reveals as (R, v) pairs - * @param compositions Optional list of composition items - * @param conditions Optional list of condition groups - * @param sig Signature over UID(ProtoTag, UserAddr, P) + * @notice Unified Commitment Payload (P) containing all attestation data + * @dev The CommitmentPayload is the core data structure signed by the operator network. + * It contains the user's address, any publicly revealed values, composition operations, + * and condition groups. The signature field contains the user's signature over the + * unique identifier UID(ProtoTag, UserAddr, P). + * @param userAddr The address of the user making the attestation + * @param values Optional array of publicly revealed (Resource, value) pairs + * @param compositions Optional array of composition operations on resources + * @param conditions Optional array of condition groups that must be satisfied + * @param sig User's signature over the payload identifier */ struct CommitmentPayload { address userAddr; @@ -77,11 +101,14 @@ interface IOpacitySDK { } /** - * @notice Struct containing all parameters needed for verification - * @param quorumNumbers The quorum numbers to check signatures for - * @param referenceBlockNumber The block number to use as reference for operator set - * @param nonSignerStakesAndSignature The non-signer stakes and signature data computed off-chain - * @param payload The unified commitment payload + * @notice Struct containing all parameters needed for BLS signature verification + * @dev This struct bundles all verification inputs required by the verify() function. + * The referenceBlockNumber must be recent (within BLOCK_STALE_MEASURE blocks) to ensure + * the operator set hasn't changed significantly since the attestation was created. + * @param quorumNumbers The quorum numbers to check signatures against (encoded as bytes) + * @param referenceBlockNumber The block number used to determine the operator set composition + * @param nonSignerStakesAndSignature BLS signature data and non-signer information computed off-chain + * @param payload The unified commitment payload containing the attested data */ struct VerificationParams { bytes quorumNumbers; @@ -90,41 +117,61 @@ interface IOpacitySDK { CommitmentPayload payload; } - /// @notice Thrown when the BLS signature verification fails + /** + * @notice Thrown when the BLS signature verification fails + * @dev This error indicates that the aggregated BLS signature does not match the expected signers + */ error InvalidSignature(); - /// @notice Thrown when the quorum threshold is not met (signatories own less than required percentage) + /** + * @notice Thrown when the quorum threshold is not met + * @dev Signatories must own at least QUORUM_THRESHOLD percent of the stake for each quorum + */ error InsufficientQuorumThreshold(); - /// @notice Thrown when the reference block number is too old (beyond BLOCK_STALE_MEASURE) + /** + * @notice Thrown when the reference block number is too old + * @dev The reference block must be within BLOCK_STALE_MEASURE blocks of the current block + */ error StaleBlockNumber(); - /// @notice Thrown when the reference block number is in the future + /** + * @notice Thrown when the reference block number is in the future + * @dev The reference block must be less than the current block number + */ error FutureBlockNumber(); /** - * @notice Compute the payload hash for signature verification - * @dev Implements UID(ProtoTag, UserAddr, P) where P is the commitment payload - * @param payload The commitment payload - * @return The payload hash + * @notice Computes the unique payload hash used for signature verification + * @dev Implements the UID(ProtoTag, UserAddr, P) computation where P is the commitment payload. + * This hash is what the operator network signs to attest to the validity of the payload data. + * @param payload The commitment payload to hash + * @return The keccak256 hash of the encoded payload */ function computePayloadHash(CommitmentPayload memory payload) external pure returns (bytes32); /** - * @notice Function to verify if a signature is valid - * @param params The verification parameters wrapped in a struct - * @return success Whether the verification succeeded + * @notice Verifies a BLS-signed attestation from the operator network + * @dev Checks that: + * 1. The reference block is not in the future + * 2. The reference block is not stale (within BLOCK_STALE_MEASURE blocks) + * 3. The BLS signature is valid + * 4. The signing operators meet the quorum threshold for all specified quorums + * @param params The verification parameters containing quorum info, block reference, and payload + * @return success True if the attestation is valid, reverts otherwise */ function verify(VerificationParams calldata params) external view returns (bool success); /** - * @notice Get the current quorum threshold - * @return The current quorum threshold percentage + * @notice Returns the current quorum threshold percentage + * @dev Signatories must control at least this percentage of stake for verification to succeed + * @return The quorum threshold as a percentage (e.g., 66 means 66%) */ function getQuorumThreshold() external view returns (uint8); /** - * @notice Get the block stale measure + * @notice Returns the maximum age of a reference block in blocks + * @dev Reference blocks older than this value will cause verification to fail with StaleBlockNumber * @return The number of blocks after which a reference block is considered stale */ function getBlockStaleMeasure() external view returns (uint32); diff --git a/src/OpacitySDK.sol b/src/OpacitySDK.sol index 93ddc81..eb2e68d 100644 --- a/src/OpacitySDK.sol +++ b/src/OpacitySDK.sol @@ -7,21 +7,52 @@ import {IOpacitySDK} from "./IOpacitySDK.sol"; /** * @title OpacitySDK - * @notice Lightweight SDK for implementing opacity verification - * @dev Inherit from this contract to add opacity verification capabilities to your contract + * @notice Abstract contract providing BLS signature verification for Opacity attestations + * @dev Inherit from this contract to add Opacity verification capabilities to your contract. + * The SDK integrates with EigenLayer's BLS signature infrastructure to verify that + * a quorum of operators have attested to the validity of private data commitments. + * + * Example usage: + * ```solidity + * contract MyConsumer is OpacitySDK { + * constructor(address _blsChecker) OpacitySDK(_blsChecker) {} + * + * function processVerifiedData(VerificationParams calldata params) external { + * require(this.verify(params), "Verification failed"); + * // Process verified data from params.payload + * } + * } + * ``` */ abstract contract OpacitySDK is IOpacitySDK { - // The BLS signature checker contract + /** + * @notice The BLS signature checker contract used for cryptographic verification + * @dev This contract is provided by EigenLayer and handles the BLS signature math + */ BLSSignatureChecker public immutable blsSignatureChecker; - // Constants for stake threshold checking + /** + * @notice Denominator used for threshold percentage calculations + * @dev QUORUM_THRESHOLD / THRESHOLD_DENOMINATOR gives the required stake fraction + */ uint8 public constant THRESHOLD_DENOMINATOR = 100; + + /** + * @notice Minimum percentage of stake required for quorum (default: 66%) + * @dev Can be modified by inheriting contracts if needed + */ uint8 public QUORUM_THRESHOLD = 66; + + /** + * @notice Maximum age of reference block in blocks (default: 300 blocks) + * @dev Attestations with older reference blocks will be rejected as stale + */ uint32 public BLOCK_STALE_MEASURE = 300; /** - * @notice Constructor for OpacitySDK - * @param _blsSignatureChecker Address of the deployed BLS signature checker contract + * @notice Initializes the OpacitySDK with the required BLS signature checker + * @dev The BLS signature checker must be deployed before this contract and cannot be changed after deployment + * @param _blsSignatureChecker Address of the deployed BLS signature checker contract (must be non-zero) */ constructor(address _blsSignatureChecker) { require(_blsSignatureChecker != address(0), "Invalid BLS signature checker address"); @@ -29,10 +60,13 @@ abstract contract OpacitySDK is IOpacitySDK { } /** - * @notice Compute the payload hash for signature verification - * @dev Implements UID(ProtoTag, UserAddr, P) where P is the commitment payload - * @param payload The commitment payload - * @return The payload hash + * @notice Computes the unique payload hash used for signature verification + * @dev Implements the UID(ProtoTag, UserAddr, P) computation where P is the commitment payload. + * The hash is computed over the userAddr, values, compositions, and conditions fields. + * Note: The signature field is intentionally excluded from the hash. + * Note: Protocol tag versioning is prepared but currently disabled. + * @param payload The commitment payload containing the data to hash + * @return The keccak256 hash of the ABI-encoded payload fields */ function computePayloadHash(CommitmentPayload memory payload) public pure returns (bytes32) { // Protocol tag for versioning (commented out for now) @@ -47,9 +81,16 @@ abstract contract OpacitySDK is IOpacitySDK { } /** - * @notice Function to verify if a signature is valid - * @param params The verification parameters wrapped in a struct - * @return success Whether the verification succeeded + * @notice Verifies a BLS-signed attestation from the Opacity operator network + * @dev Performs the following verification steps: + * 1. Validates the reference block is not in the future (reverts with FutureBlockNumber) + * 2. Validates the reference block is not stale (reverts with StaleBlockNumber) + * 3. Computes the payload hash and verifies BLS signatures via the signature checker + * 4. Checks that each quorum meets the stake threshold (reverts with InsufficientQuorumThreshold) + * + * This function is view-only and does not modify state. + * @param params The verification parameters containing quorum numbers, block reference, signature data, and payload + * @return success Always returns true if verification succeeds; reverts on any failure */ function verify(VerificationParams calldata params) external view returns (bool success) { // Check block number validity @@ -65,7 +106,7 @@ abstract contract OpacitySDK is IOpacitySDK { msgHash, params.quorumNumbers, params.referenceBlockNumber, params.nonSignerStakesAndSignature ); - // Check that signatories own at least 66% of each quorum + // Check that signatories own at least QUORUM_THRESHOLD% of each quorum for (uint256 i = 0; i < params.quorumNumbers.length; i++) { require( stakeTotals.signedStakeForQuorum[i] * THRESHOLD_DENOMINATOR @@ -78,15 +119,19 @@ abstract contract OpacitySDK is IOpacitySDK { } /** - * @notice Get the current quorum threshold - * @return The current quorum threshold percentage + * @notice Returns the current quorum threshold percentage + * @dev The threshold determines what fraction of stake must sign for verification to succeed. + * For example, 66 means 66% of the total quorum stake must have signed. + * @return The quorum threshold as a percentage (0-100) */ function getQuorumThreshold() external view returns (uint8) { return QUORUM_THRESHOLD; } /** - * @notice Get the block stale measure + * @notice Returns the maximum age of a reference block in blocks + * @dev Reference blocks older than current block - BLOCK_STALE_MEASURE will be rejected. + * This prevents replay attacks with old operator sets. * @return The number of blocks after which a reference block is considered stale */ function getBlockStaleMeasure() external view returns (uint32) { diff --git a/src/examples/SimpleVerificationConsumer.sol b/src/examples/SimpleVerificationConsumer.sol index aaff8b1..3690b6b 100644 --- a/src/examples/SimpleVerificationConsumer.sol +++ b/src/examples/SimpleVerificationConsumer.sol @@ -5,19 +5,41 @@ import "../OpacitySDK.sol"; import "../IOpacitySDK.sol"; import "@eigenlayer-middleware/interfaces/IBLSSignatureChecker.sol"; +/** + * @title SimpleVerificationConsumer + * @notice A minimal example contract demonstrating basic Opacity attestation verification + * @dev This contract shows the simplest possible integration with OpacitySDK. + * It verifies attestations and emits an event on success, but does not store any data. + * Use this as a template for stateless verification use cases. + * + * Example usage: + * ```solidity + * SimpleVerificationConsumer consumer = new SimpleVerificationConsumer(blsCheckerAddress); + * bool success = consumer.verifyUserData(verificationParams); + * ``` + */ contract SimpleVerificationConsumer is OpacitySDK { + /** + * @notice Emitted when user data verification is attempted + * @param user The address of the user whose data was verified + * @param isValid Whether the verification succeeded + */ event DataVerified(address indexed user, bool isValid); /** - * @notice Constructor for SimpleVerificationConsumer + * @notice Initializes the consumer with the BLS signature checker * @param _blsSignatureChecker Address of the deployed BLS signature checker contract */ constructor(address _blsSignatureChecker) OpacitySDK(_blsSignatureChecker) {} /** - * @notice Verify user data using VerificationParams struct - * @dev Primary interface - cleaner way to use the OpacitySDK - * @param params The VerificationParams struct containing all verification parameters + * @notice Verifies user data and emits a verification event + * @dev This function wraps the OpacitySDK verify() call in a try-catch to provide + * a boolean return value instead of reverting on failure. The verification result + * is emitted as a DataVerified event for off-chain tracking. + * @param params The VerificationParams struct containing quorum numbers, reference block, + * BLS signature data, and the commitment payload + * @return True if verification succeeded, false if verification failed or reverted */ function verifyUserData(IOpacitySDK.VerificationParams calldata params) public returns (bool) { try this.verify(params) returns (bool verified) { diff --git a/src/examples/StorageQueryConsumer.sol b/src/examples/StorageQueryConsumer.sol index 4951417..d878519 100644 --- a/src/examples/StorageQueryConsumer.sol +++ b/src/examples/StorageQueryConsumer.sol @@ -7,32 +7,68 @@ import "@eigenlayer-middleware/interfaces/IBLSSignatureChecker.sol"; /** * @title StorageQueryConsumer - * @notice Example contract demonstrating basic opacity verification using OpacitySDK - * @dev This contract shows how to verify private data and retrieve the verified values + * @notice Example contract demonstrating stateful Opacity verification with data storage + * @dev This contract shows a more advanced integration with OpacitySDK that: + * - Stores verification results persistently on-chain + * - Tracks publicly revealed values from attestations + * - Provides query functions for verification status and expiration checking + * + * Use this as a template for applications that need to: + * - Remember past verifications + * - Access revealed values after verification + * - Implement verification expiration logic */ contract StorageQueryConsumer is OpacitySDK { + /** + * @notice Stores the result of a verification attempt for a user + * @param isVerified Whether the verification succeeded + * @param payloadHash The hash of the verified commitment payload + * @param timestamp The block timestamp when verification occurred + */ struct VerificationResult { bool isVerified; bytes32 payloadHash; uint256 timestamp; } + /** + * @notice Maps user addresses to their most recent verification result + * @dev Each user can only have one active verification at a time + */ mapping(address => VerificationResult) public userVerifications; + + /** + * @notice Maps user addresses to their array of publicly revealed values + * @dev Values are replaced entirely on each new verification + */ mapping(address => IOpacitySDK.ValueReveal[]) public userValues; + /** + * @notice Emitted when a verification attempt is made for a user + * @param user The address of the user whose data was verified + * @param payloadHash The hash of the commitment payload that was verified + * @param success Whether the verification succeeded + */ event DataVerified(address indexed user, bytes32 payloadHash, bool success); /** - * @notice Constructor for StorageQueryConsumer + * @notice Initializes the consumer with the BLS signature checker * @param _blsSignatureChecker Address of the deployed BLS signature checker contract */ constructor(address _blsSignatureChecker) OpacitySDK(_blsSignatureChecker) {} /** - * @notice Verify commitment data using VerificationParams struct - * @dev Primary interface that directly accepts the verification parameters struct - * @param params The verification parameters wrapped in a struct - * @return success Whether verification succeeded + * @notice Verifies a commitment and stores the result and revealed values + * @dev This function: + * 1. Attempts verification via OpacitySDK.verify() + * 2. On success, stores the verification result with timestamp + * 3. Replaces any existing revealed values with the new ones + * 4. Emits a DataVerified event + * + * Note: Any previous verification and values for this user are overwritten. + * @param params The verification parameters containing quorum info, reference block, + * BLS signature data, and the commitment payload + * @return success True if verification succeeded, false if it failed or reverted */ function verifyCommitment(IOpacitySDK.VerificationParams calldata params) external returns (bool success) { try this.verify(params) returns (bool verified) { @@ -56,20 +92,24 @@ contract StorageQueryConsumer is OpacitySDK { } /** - * @notice Get the verified values for a user (public reveals only) - * @param user The user to check - * @return values Array of public value reveals + * @notice Retrieves all publicly revealed values for a user + * @dev Returns an empty array if the user has no stored verification or no revealed values. + * These values were disclosed by the user as part of their attestation. + * @param user The address of the user to query + * @return values Array of ValueReveal structs containing resource and value pairs */ function getUserValues(address user) external view returns (IOpacitySDK.ValueReveal[] memory values) { return userValues[user]; } /** - * @notice Check if a user has valid verification - * @param user The user to check - * @return isValid Whether the user has valid verification - * @return payloadHash The hash of the commitment payload - * @return timestamp When the verification was made + * @notice Retrieves the verification status and metadata for a user + * @dev Returns default values (false, 0x0, 0) if the user has never been verified. + * Note: This does not check expiration - use isVerificationValid() for that. + * @param user The address of the user to query + * @return isValid Whether the user's most recent verification succeeded + * @return payloadHash The keccak256 hash of the verified commitment payload + * @return timestamp The block timestamp when verification occurred */ function getUserVerification(address user) external @@ -81,11 +121,16 @@ contract StorageQueryConsumer is OpacitySDK { } /** - * @notice Check if a verification is still valid (not expired) - * @param user The user to check - * @param maxAge Maximum age of verification in seconds - * @return isValid Whether the verification is still valid - * @return payloadHash The hash of the commitment payload if still valid + * @notice Checks if a user's verification is valid and not expired + * @dev A verification is valid if: + * 1. The user has a stored verification that succeeded (isVerified = true) + * 2. The verification occurred within maxAge seconds of the current block + * + * Returns bytes32(0) for payloadHash if the verification is expired or invalid. + * @param user The address of the user to check + * @param maxAge Maximum allowed age of the verification in seconds + * @return isValid True if the user has a valid, non-expired verification + * @return payloadHash The payload hash if valid, or bytes32(0) if expired/invalid */ function isVerificationValid(address user, uint256 maxAge) external @@ -98,10 +143,12 @@ contract StorageQueryConsumer is OpacitySDK { } /** - * @notice Get a specific value reveal for a user by index - * @param user The user to check - * @param index The index of the value reveal - * @return value The value reveal at the specified index + * @notice Retrieves a specific revealed value by index + * @dev Useful for iterating through values without loading the entire array. + * Reverts with "Index out of bounds" if the index exceeds the array length. + * @param user The address of the user to query + * @param index The zero-based index of the value reveal to retrieve + * @return value The ValueReveal struct at the specified index */ function getUserValueByIndex(address user, uint256 index) external diff --git a/test/ExampleConsumers.t.sol b/test/ExampleConsumers.t.sol index e8855c1..0607672 100644 --- a/test/ExampleConsumers.t.sol +++ b/test/ExampleConsumers.t.sol @@ -9,14 +9,34 @@ import "../src/examples/StorageQueryConsumer.sol"; /** * @title ExampleConsumersTest - * @notice Tests for the example consumer contracts (SimpleVerificationConsumer and StorageQueryConsumer) + * @notice Unit tests for the example consumer contracts + * @dev Tests both SimpleVerificationConsumer and StorageQueryConsumer to verify: + * - Correct OpacitySDK configuration inheritance + * - Default parameter values (quorum threshold, block stale measure) + * - Payload hash computation functionality + * - Storage mechanisms for verified data + * + * Note: These tests use a mocked BLS signature checker and focus on + * contract configuration and data handling, not actual BLS verification. */ contract ExampleConsumersTest is Test { + /// @notice Instance of the simple verification consumer for testing SimpleVerificationConsumer public simpleConsumer; + + /// @notice Instance of the storage query consumer for testing StorageQueryConsumer public storageConsumer; + + /// @notice Mock address for the BLS signature checker address public blsSignatureChecker; + + /// @notice Test user address for payload construction address public testUser; + /** + * @notice Sets up the test environment before each test + * @dev Deploys both consumer contracts with a mocked BLS signature checker. + * The mock has minimal bytecode (0x00) to satisfy the constructor check. + */ function setUp() public { // Mock BLS signature checker address blsSignatureChecker = address(0x1234); @@ -28,26 +48,47 @@ contract ExampleConsumersTest is Test { storageConsumer = new StorageQueryConsumer(blsSignatureChecker); } + /** + * @notice Tests that SimpleVerificationConsumer inherits the correct quorum threshold + * @dev Verifies the default 66% threshold is inherited from OpacitySDK + */ function testSimpleConsumerGetQuorumThreshold() public { uint8 threshold = simpleConsumer.getQuorumThreshold(); assertEq(threshold, 66, "Quorum threshold should be 66%"); } + /** + * @notice Tests that SimpleVerificationConsumer inherits the correct block stale measure + * @dev Verifies the default 300 block limit is inherited from OpacitySDK + */ function testSimpleConsumerGetBlockStaleMeasure() public { uint32 staleMeasure = simpleConsumer.getBlockStaleMeasure(); assertEq(staleMeasure, 300, "Block stale measure should be 300 blocks"); } + /** + * @notice Tests that StorageQueryConsumer inherits the correct quorum threshold + * @dev Verifies the default 66% threshold is inherited from OpacitySDK + */ function testStorageConsumerGetQuorumThreshold() public { uint8 threshold = storageConsumer.getQuorumThreshold(); assertEq(threshold, 66, "Quorum threshold should be 66%"); } + /** + * @notice Tests that StorageQueryConsumer inherits the correct block stale measure + * @dev Verifies the default 300 block limit is inherited from OpacitySDK + */ function testStorageConsumerGetBlockStaleMeasure() public { uint32 staleMeasure = storageConsumer.getBlockStaleMeasure(); assertEq(staleMeasure, 300, "Block stale measure should be 300 blocks"); } + /** + * @notice Tests that StorageQueryConsumer correctly initializes with empty user data + * @dev Verifies that getUserValues returns an empty array for a user with no stored values. + * Note: Actual verification cannot be tested without a real BLS signature checker. + */ function testStorageQueryConsumerValueStorage() public { // Create a simple commitment with value reveals IOpacitySDK.Resource memory resource = @@ -75,6 +116,10 @@ contract ExampleConsumersTest is Test { // But we can test the data structures and storage } + /** + * @notice Tests that StorageQueryConsumer correctly computes payload hashes + * @dev Verifies the inherited computePayloadHash function produces non-zero hashes + */ function testStorageConsumerPayloadHashing() public { // Test that the storage consumer can compute payload hashes correctly IOpacitySDK.Resource memory resource = diff --git a/test/OpacitySDK.t.sol b/test/OpacitySDK.t.sol index 06880b5..0257c64 100644 --- a/test/OpacitySDK.t.sol +++ b/test/OpacitySDK.t.sol @@ -8,13 +8,30 @@ import "../src/examples/SimpleVerificationConsumer.sol"; /** * @title OpacitySDKTest - * @notice Core tests for OpacitySDK payload hash computation and data structures + * @notice Unit tests for OpacitySDK payload hash computation and data structures + * @dev Tests the core functionality of the OpacitySDK, specifically: + * - Payload hash computation for various payload configurations + * - Data structure encoding (Resources, ValueReveals, Compositions, Conditions) + * - Hash determinism and uniqueness properties + * + * Note: These tests use a mocked BLS signature checker and do not test + * actual BLS signature verification. See integration tests for full verification testing. */ contract OpacitySDKTest is Test { + /// @notice The consumer contract instance used for testing SimpleVerificationConsumer public consumer; + + /// @notice Mock address for the BLS signature checker address public blsSignatureChecker; + + /// @notice Test user address used in payload construction address public testUser; + /** + * @notice Sets up the test environment before each test + * @dev Deploys a SimpleVerificationConsumer with a mocked BLS signature checker. + * The mock checker has minimal bytecode (0x00) to allow deployment. + */ function setUp() public { // Mock BLS signature checker address blsSignatureChecker = address(0x1234); @@ -25,6 +42,11 @@ contract OpacitySDKTest is Test { consumer = new SimpleVerificationConsumer(blsSignatureChecker); } + /** + * @notice Tests basic payload hash computation with empty arrays + * @dev Verifies that a minimal payload with no values, compositions, or conditions + * produces a non-zero hash + */ function testComputePayloadHashBasic() public { IOpacitySDK.ValueReveal[] memory values = new IOpacitySDK.ValueReveal[](0); IOpacitySDK.Composition[] memory compositions = new IOpacitySDK.Composition[](0); @@ -42,6 +64,11 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash should not be zero"); } + /** + * @notice Tests payload hash computation with value reveals + * @dev Creates two bank balance resources with numeric values and verifies + * the resulting hash is non-zero + */ function testComputePayloadHashWithValues() public { // Create resources IOpacitySDK.Resource memory resource1 = @@ -70,6 +97,11 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash with values should not be zero"); } + /** + * @notice Tests payload hash computation with a sum composition + * @dev Creates a composition that sums two bank balance resources + * and verifies the hash is non-zero + */ function testComputePayloadHashWithCompositions() public { // Create resources IOpacitySDK.Resource memory resource1 = @@ -101,6 +133,10 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash with compositions should not be zero"); } + /** + * @notice Tests payload hash computation with a greater-than condition + * @dev Creates a condition requiring balance > 500 and verifies the hash is non-zero + */ function testComputePayloadHashWithConditions() public { // Create resource IOpacitySDK.Resource memory resource = @@ -132,6 +168,15 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash with conditions should not be zero"); } + /** + * @notice Tests payload hash computation with a comprehensive payload + * @dev Creates a complete payload with: + * - 3 value reveals (2 bank balances + 1 employer) + * - 1 sum composition + * - 3 conditions (balance thresholds + substring check) + * - A mock signature + * Verifies all components hash correctly together + */ function testFullCommitmentPayload() public { // Create resources IOpacitySDK.Resource memory bankResource1 = @@ -198,6 +243,11 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Full commitment payload hash should not be zero"); } + /** + * @notice Tests payload hash with multiple condition atoms in a single group + * @dev Creates a condition group with two gt conditions (> 100 AND > 500) + * applied to the same resource, verifying AND logic encoding + */ function testMultipleConditionAtoms() public { // Test multiple condition atoms in one group IOpacitySDK.Resource memory resource = @@ -228,6 +278,11 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload with multiple condition atoms should hash correctly"); } + /** + * @notice Tests payload hash with a concat composition + * @dev Creates a composition that concatenates firstName and lastName resources, + * verifying string composition encoding + */ function testConcatComposition() public { // Test concat operation IOpacitySDK.Resource memory resource1 = @@ -258,6 +313,11 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Concat composition should hash correctly"); } + /** + * @notice Tests that different user addresses produce different hashes + * @dev Creates two identical payloads differing only in userAddr, + * verifying that the hash is sensitive to the user address + */ function testEmptyPayloadDifferentUsers() public { // Test that same payload structure with different users produces different hashes IOpacitySDK.ValueReveal[] memory values = new IOpacitySDK.ValueReveal[](0); @@ -286,6 +346,15 @@ contract OpacitySDKTest is Test { assertNotEq(hash1, hash2, "Different users should produce different payload hashes"); } + /** + * @notice Tests payload hash determinism with a known expected value + * @dev Uses hardcoded inputs and expected output to verify: + * 1. Hash computation is deterministic across runs + * 2. Hash matches off-chain computed value + * 3. Any changes to encoding would be detected as test failures + * + * Expected hash: 0xa3f9c50a7b411f721324549daa11a23f82fc9defd756075a3f76edbbf667aef2 + */ function testHardcodedPayloadHashWithValueReveals() public { // This test uses a fixed example with hardcoded expected hash // to ensure the payload hash computation remains consistent From 4e548378d02ae023dfbe436df78fa6e49d050963 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Wed, 3 Dec 2025 15:02:48 -0500 Subject: [PATCH 2/6] Fix forge fmt formatting in test files Collapse multi-line struct initializations to single lines per forge fmt standards. --- test/ExampleConsumers.t.sol | 12 ++------- test/OpacitySDK.t.sol | 54 +++++++------------------------------ 2 files changed, 11 insertions(+), 55 deletions(-) diff --git a/test/ExampleConsumers.t.sol b/test/ExampleConsumers.t.sol index 0607672..21aac01 100644 --- a/test/ExampleConsumers.t.sol +++ b/test/ExampleConsumers.t.sol @@ -101,11 +101,7 @@ contract ExampleConsumersTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); // Get stored values (should be empty initially) @@ -132,11 +128,7 @@ contract ExampleConsumersTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = storageConsumer.computePayloadHash(payload); diff --git a/test/OpacitySDK.t.sol b/test/OpacitySDK.t.sol index 0257c64..5905cf0 100644 --- a/test/OpacitySDK.t.sol +++ b/test/OpacitySDK.t.sol @@ -53,11 +53,7 @@ contract OpacitySDKTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = consumer.computePayloadHash(payload); @@ -86,11 +82,7 @@ contract OpacitySDKTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = consumer.computePayloadHash(payload); @@ -122,11 +114,7 @@ contract OpacitySDKTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = consumer.computePayloadHash(payload); @@ -157,11 +145,7 @@ contract OpacitySDKTest is Test { IOpacitySDK.Composition[] memory compositions = new IOpacitySDK.Composition[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = consumer.computePayloadHash(payload); @@ -267,11 +251,7 @@ contract OpacitySDKTest is Test { IOpacitySDK.Composition[] memory compositions = new IOpacitySDK.Composition[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = consumer.computePayloadHash(payload); @@ -302,11 +282,7 @@ contract OpacitySDKTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash = consumer.computePayloadHash(payload); @@ -325,19 +301,11 @@ contract OpacitySDKTest is Test { IOpacitySDK.ConditionGroup[] memory conditions = new IOpacitySDK.ConditionGroup[](0); IOpacitySDK.CommitmentPayload memory payload1 = IOpacitySDK.CommitmentPayload({ - userAddr: testUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: testUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); IOpacitySDK.CommitmentPayload memory payload2 = IOpacitySDK.CommitmentPayload({ - userAddr: address(0x9999), - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: address(0x9999), values: values, compositions: compositions, conditions: conditions, sig: hex"" }); bytes32 hash1 = consumer.computePayloadHash(payload1); @@ -380,11 +348,7 @@ contract OpacitySDKTest is Test { // Create the commitment payload IOpacitySDK.CommitmentPayload memory payload = IOpacitySDK.CommitmentPayload({ - userAddr: specificUser, - values: values, - compositions: compositions, - conditions: conditions, - sig: hex"" + userAddr: specificUser, values: values, compositions: compositions, conditions: conditions, sig: hex"" }); // Compute the hash From 84c299016e7a0faad2dac8289aee2fd6dafa1e2d Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Wed, 3 Dec 2025 15:04:33 -0500 Subject: [PATCH 3/6] Untrack foundry.lock and add to .gitignore --- .gitignore | 1 + foundry.lock | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 foundry.lock diff --git a/.gitignore b/.gitignore index 85198aa..ce988cd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ docs/ # Dotenv file .env +foundry.lock diff --git a/foundry.lock b/foundry.lock deleted file mode 100644 index 3dc4ee9..0000000 --- a/foundry.lock +++ /dev/null @@ -1,8 +0,0 @@ -{ - "lib/eigenlayer-middleware": { - "rev": "f5adbcac55d9336cd646ce71bc467aa7e20f1a12" - }, - "lib/forge-std": { - "rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505" - } -} \ No newline at end of file From 8d9b4b1d7c2285d9bc6a7efb0911ed05a778f59e Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Wed, 3 Dec 2025 15:05:01 -0500 Subject: [PATCH 4/6] Remove NatSpec from deploy script --- script/Deploy.s.sol | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 761b547..a3b3b28 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -6,41 +6,10 @@ import "@eigenlayer-middleware/BLSSignatureChecker.sol"; import "@eigenlayer-middleware/interfaces/IRegistryCoordinator.sol"; import "../src/examples/SimpleVerificationConsumer.sol"; -/** - * @title Deploy - * @notice Foundry deployment script for OpacitySDK example contracts - * @dev This script deploys the SimpleVerificationConsumer contract using an existing - * BLS signature checker. It requires: - * - PRIVATE_KEY environment variable set with the deployer's private key - * - A deployed BLS signature checker address - * - A deployed registry coordinator address - * - * Usage: - * ```bash - * forge script script/Deploy.s.sol:Deploy \ - * --sig "run(address,address)" \ - * --rpc-url $RPC_URL --broadcast - * ``` - */ contract Deploy is Script { - /** - * @notice Reference to the BLS signature checker contract - */ BLSSignatureChecker public blsSignatureChecker; - - /** - * @notice The deployed SimpleVerificationConsumer instance - */ SimpleVerificationConsumer public simpleVerificationConsumer; - /** - * @notice Main deployment entrypoint - * @dev Deploys a SimpleVerificationConsumer linked to the provided BLS signature checker. - * Reads PRIVATE_KEY from environment variables for transaction signing. - * Logs deployment progress and final addresses to console. - * @param blsSignatureCheckerAddress Address of an already-deployed BLS signature checker (must be non-zero) - * @param registryCoordinator Address of the EigenLayer registry coordinator (must be non-zero, used for logging) - */ function run(address blsSignatureCheckerAddress, address registryCoordinator) external { require(blsSignatureCheckerAddress != address(0), "Invalid BLS address"); require(registryCoordinator != address(0), "Invalid registry coordinator address"); @@ -65,12 +34,6 @@ contract Deploy is Script { printDeploymentSummary(); } - /** - * @notice Prints a summary of all deployed contracts and verifies linkage - * @dev Internal helper function called after deployment completes. - * Verifies that the SimpleVerificationConsumer is correctly linked - * to the BLS signature checker by comparing stored addresses. - */ function printDeploymentSummary() internal view { console.log("\n========================================"); console.log(" DEPLOYMENT SUMMARY"); From f634479186a90f45a743b3f07e752ff75b3d5236 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Wed, 3 Dec 2025 15:05:58 -0500 Subject: [PATCH 5/6] Remove specific condition types from CondAtom docs --- src/IOpacitySDK.sol | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/IOpacitySDK.sol b/src/IOpacitySDK.sol index aed703d..1fe5ac1 100644 --- a/src/IOpacitySDK.sol +++ b/src/IOpacitySDK.sol @@ -56,11 +56,8 @@ interface IOpacitySDK { /** * @notice Conditional atom representing a single condition check * @dev CondAtom structures define individual conditions that can be applied to resources. - * Supported condition types: - * - "substr": Checks if the resource value contains the specified substring - * - "gt": Checks if the numeric resource value is greater than the threshold - * @param atomType The type of condition to evaluate ("substr" or "gt") - * @param value The condition parameter (substring to find, or numeric threshold as string) + * @param atomType The type of condition to evaluate + * @param value The condition parameter */ struct CondAtom { string atomType; From 27e674d7c5216abe5b442989feb5a576e3d38180 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Wed, 3 Dec 2025 15:07:49 -0500 Subject: [PATCH 6/6] Remove NatSpec from test files --- test/ExampleConsumers.t.sol | 49 ------------------------- test/OpacitySDK.t.sol | 73 ------------------------------------- 2 files changed, 122 deletions(-) diff --git a/test/ExampleConsumers.t.sol b/test/ExampleConsumers.t.sol index 21aac01..da59a19 100644 --- a/test/ExampleConsumers.t.sol +++ b/test/ExampleConsumers.t.sol @@ -7,36 +7,12 @@ import "../src/IOpacitySDK.sol"; import "../src/examples/SimpleVerificationConsumer.sol"; import "../src/examples/StorageQueryConsumer.sol"; -/** - * @title ExampleConsumersTest - * @notice Unit tests for the example consumer contracts - * @dev Tests both SimpleVerificationConsumer and StorageQueryConsumer to verify: - * - Correct OpacitySDK configuration inheritance - * - Default parameter values (quorum threshold, block stale measure) - * - Payload hash computation functionality - * - Storage mechanisms for verified data - * - * Note: These tests use a mocked BLS signature checker and focus on - * contract configuration and data handling, not actual BLS verification. - */ contract ExampleConsumersTest is Test { - /// @notice Instance of the simple verification consumer for testing SimpleVerificationConsumer public simpleConsumer; - - /// @notice Instance of the storage query consumer for testing StorageQueryConsumer public storageConsumer; - - /// @notice Mock address for the BLS signature checker address public blsSignatureChecker; - - /// @notice Test user address for payload construction address public testUser; - /** - * @notice Sets up the test environment before each test - * @dev Deploys both consumer contracts with a mocked BLS signature checker. - * The mock has minimal bytecode (0x00) to satisfy the constructor check. - */ function setUp() public { // Mock BLS signature checker address blsSignatureChecker = address(0x1234); @@ -48,47 +24,26 @@ contract ExampleConsumersTest is Test { storageConsumer = new StorageQueryConsumer(blsSignatureChecker); } - /** - * @notice Tests that SimpleVerificationConsumer inherits the correct quorum threshold - * @dev Verifies the default 66% threshold is inherited from OpacitySDK - */ function testSimpleConsumerGetQuorumThreshold() public { uint8 threshold = simpleConsumer.getQuorumThreshold(); assertEq(threshold, 66, "Quorum threshold should be 66%"); } - /** - * @notice Tests that SimpleVerificationConsumer inherits the correct block stale measure - * @dev Verifies the default 300 block limit is inherited from OpacitySDK - */ function testSimpleConsumerGetBlockStaleMeasure() public { uint32 staleMeasure = simpleConsumer.getBlockStaleMeasure(); assertEq(staleMeasure, 300, "Block stale measure should be 300 blocks"); } - /** - * @notice Tests that StorageQueryConsumer inherits the correct quorum threshold - * @dev Verifies the default 66% threshold is inherited from OpacitySDK - */ function testStorageConsumerGetQuorumThreshold() public { uint8 threshold = storageConsumer.getQuorumThreshold(); assertEq(threshold, 66, "Quorum threshold should be 66%"); } - /** - * @notice Tests that StorageQueryConsumer inherits the correct block stale measure - * @dev Verifies the default 300 block limit is inherited from OpacitySDK - */ function testStorageConsumerGetBlockStaleMeasure() public { uint32 staleMeasure = storageConsumer.getBlockStaleMeasure(); assertEq(staleMeasure, 300, "Block stale measure should be 300 blocks"); } - /** - * @notice Tests that StorageQueryConsumer correctly initializes with empty user data - * @dev Verifies that getUserValues returns an empty array for a user with no stored values. - * Note: Actual verification cannot be tested without a real BLS signature checker. - */ function testStorageQueryConsumerValueStorage() public { // Create a simple commitment with value reveals IOpacitySDK.Resource memory resource = @@ -112,10 +67,6 @@ contract ExampleConsumersTest is Test { // But we can test the data structures and storage } - /** - * @notice Tests that StorageQueryConsumer correctly computes payload hashes - * @dev Verifies the inherited computePayloadHash function produces non-zero hashes - */ function testStorageConsumerPayloadHashing() public { // Test that the storage consumer can compute payload hashes correctly IOpacitySDK.Resource memory resource = diff --git a/test/OpacitySDK.t.sol b/test/OpacitySDK.t.sol index 5905cf0..719d51a 100644 --- a/test/OpacitySDK.t.sol +++ b/test/OpacitySDK.t.sol @@ -6,32 +6,11 @@ import "../src/OpacitySDK.sol"; import "../src/IOpacitySDK.sol"; import "../src/examples/SimpleVerificationConsumer.sol"; -/** - * @title OpacitySDKTest - * @notice Unit tests for OpacitySDK payload hash computation and data structures - * @dev Tests the core functionality of the OpacitySDK, specifically: - * - Payload hash computation for various payload configurations - * - Data structure encoding (Resources, ValueReveals, Compositions, Conditions) - * - Hash determinism and uniqueness properties - * - * Note: These tests use a mocked BLS signature checker and do not test - * actual BLS signature verification. See integration tests for full verification testing. - */ contract OpacitySDKTest is Test { - /// @notice The consumer contract instance used for testing SimpleVerificationConsumer public consumer; - - /// @notice Mock address for the BLS signature checker address public blsSignatureChecker; - - /// @notice Test user address used in payload construction address public testUser; - /** - * @notice Sets up the test environment before each test - * @dev Deploys a SimpleVerificationConsumer with a mocked BLS signature checker. - * The mock checker has minimal bytecode (0x00) to allow deployment. - */ function setUp() public { // Mock BLS signature checker address blsSignatureChecker = address(0x1234); @@ -42,11 +21,6 @@ contract OpacitySDKTest is Test { consumer = new SimpleVerificationConsumer(blsSignatureChecker); } - /** - * @notice Tests basic payload hash computation with empty arrays - * @dev Verifies that a minimal payload with no values, compositions, or conditions - * produces a non-zero hash - */ function testComputePayloadHashBasic() public { IOpacitySDK.ValueReveal[] memory values = new IOpacitySDK.ValueReveal[](0); IOpacitySDK.Composition[] memory compositions = new IOpacitySDK.Composition[](0); @@ -60,11 +34,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash should not be zero"); } - /** - * @notice Tests payload hash computation with value reveals - * @dev Creates two bank balance resources with numeric values and verifies - * the resulting hash is non-zero - */ function testComputePayloadHashWithValues() public { // Create resources IOpacitySDK.Resource memory resource1 = @@ -89,11 +58,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash with values should not be zero"); } - /** - * @notice Tests payload hash computation with a sum composition - * @dev Creates a composition that sums two bank balance resources - * and verifies the hash is non-zero - */ function testComputePayloadHashWithCompositions() public { // Create resources IOpacitySDK.Resource memory resource1 = @@ -121,10 +85,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash with compositions should not be zero"); } - /** - * @notice Tests payload hash computation with a greater-than condition - * @dev Creates a condition requiring balance > 500 and verifies the hash is non-zero - */ function testComputePayloadHashWithConditions() public { // Create resource IOpacitySDK.Resource memory resource = @@ -152,15 +112,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload hash with conditions should not be zero"); } - /** - * @notice Tests payload hash computation with a comprehensive payload - * @dev Creates a complete payload with: - * - 3 value reveals (2 bank balances + 1 employer) - * - 1 sum composition - * - 3 conditions (balance thresholds + substring check) - * - A mock signature - * Verifies all components hash correctly together - */ function testFullCommitmentPayload() public { // Create resources IOpacitySDK.Resource memory bankResource1 = @@ -227,11 +178,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Full commitment payload hash should not be zero"); } - /** - * @notice Tests payload hash with multiple condition atoms in a single group - * @dev Creates a condition group with two gt conditions (> 100 AND > 500) - * applied to the same resource, verifying AND logic encoding - */ function testMultipleConditionAtoms() public { // Test multiple condition atoms in one group IOpacitySDK.Resource memory resource = @@ -258,11 +204,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Payload with multiple condition atoms should hash correctly"); } - /** - * @notice Tests payload hash with a concat composition - * @dev Creates a composition that concatenates firstName and lastName resources, - * verifying string composition encoding - */ function testConcatComposition() public { // Test concat operation IOpacitySDK.Resource memory resource1 = @@ -289,11 +230,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash, bytes32(0), "Concat composition should hash correctly"); } - /** - * @notice Tests that different user addresses produce different hashes - * @dev Creates two identical payloads differing only in userAddr, - * verifying that the hash is sensitive to the user address - */ function testEmptyPayloadDifferentUsers() public { // Test that same payload structure with different users produces different hashes IOpacitySDK.ValueReveal[] memory values = new IOpacitySDK.ValueReveal[](0); @@ -314,15 +250,6 @@ contract OpacitySDKTest is Test { assertNotEq(hash1, hash2, "Different users should produce different payload hashes"); } - /** - * @notice Tests payload hash determinism with a known expected value - * @dev Uses hardcoded inputs and expected output to verify: - * 1. Hash computation is deterministic across runs - * 2. Hash matches off-chain computed value - * 3. Any changes to encoding would be detected as test failures - * - * Expected hash: 0xa3f9c50a7b411f721324549daa11a23f82fc9defd756075a3f76edbbf667aef2 - */ function testHardcodedPayloadHashWithValueReveals() public { // This test uses a fixed example with hardcoded expected hash // to ensure the payload hash computation remains consistent