Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update erc-7007.md to add opML compatibility #1

Merged
merged 11 commits into from
Jan 10, 2024
20 changes: 15 additions & 5 deletions ERCS/erc-7007.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
---
eip: 7007
title: Zero-Knowledge AI-Generated Content Token
title: AI-Generated Content Token
description: An ERC-721 extension interface for zkML based AIGC-NFTs.
author: Cathie So (@socathie), Xiaohang Yu (@xhyumiracle), Huaizhe Xu (@HuaizheXu), Kartin <[email protected]>
author: Cathie So (@socathie), Xiaohang Yu (@xhyumiracle), Huaizhe Xu (@HuaizheXu), Kartin <[email protected]>, Lee Ting Ting (@tina1998612)
discussions-to: https://ethereum-magicians.org/t/eip-7007-zkml-aigc-nfts-an-erc-721-extension-interface-for-zkml-based-aigc-nfts/14216
status: Draft
type: Standards Track
category: ERC
created: 2023-05-10
updated: 2023-12-22
requires: 165, 721
---

## Abstract

The Zero-Knowledge Machine Lerning (zkML) AI-Generated Content (AIGC) non-fungible token (NFT) standard is an extension of the [ERC-721](./eip-721.md) token standard for AIGC. It proposes a set of interfaces for basic interactions and enumerable interactions for AIGC-NFTs. The standard includes a new mint event and a JSON schema for AIGC-NFT metadata. Additionally, it incorporates zkML capabilities to enable verification of AIGC-NFT ownership. In this standard, the `tokenId` is indexed by the `prompt`.
The AI-Generated Content (AIGC) non-fungible token (NFT) standard is an extension of the [ERC-721](./eip-721.md) token standard for AIGC. It proposes a set of interfaces for basic interactions and enumerable interactions for AIGC-NFTs. The standard includes a new mint event and a JSON schema for AIGC-NFT metadata. Additionally, it incorporates zkML and opML capabilities to enable verification of AIGC-NFT ownership. In this standard, the `tokenId` is indexed by the `prompt`.

## Motivation

The zkML AIGC-NFTs standard aims to extend the existing [ERC-721](./eip-721.md) token standard to accommodate the unique requirements of AI-Generated Content NFTs representing models in a collection. This standard provides interfaces to use zkML to verify whether or not the AIGC data for an NFT is generated from a certain ML model with certain input (prompt). The proposed interfaces allow for additional functionality related to minting, verifying, and enumerating AIGC-NFTs. Additionally, the metadata schema provides a structured format for storing information related to AIGC-NFTs, such as the prompt used to generate the content and the proof of ownership.
The AIGC-NFTs standard aims to extend the existing [ERC-721](./eip-721.md) token standard to accommodate the unique requirements of AI-Generated Content NFTs representing models in a collection. This standard provides interfaces to use zkML or opML to verify whether or not the AIGC data for an NFT is generated from a certain ML model with certain input (prompt). The proposed interfaces allow for additional functionality related to minting, verifying, and enumerating AIGC-NFTs. Additionally, the metadata schema provides a structured format for storing information related to AIGC-NFTs, such as the prompt used to generate the content and the proof of ownership.

With this standard, model owners can publish their trained model and its ZKP verifier to Ethereum. Any user can claim an input (prompt) and publish the inference task, any node that maintains the model and the proving circuit can perform the inference and proving, then submit the output of inference and the ZK proof for the inference trace into the verifier that is deployed by the model owner. The user that initiates the inference task will own the output for the inference of that model and input (prompt).
There are two methods of verification for this standard. One is zkML and the other is opML. Developers can choose their preferred verfication method.

In the zkML scenario, model owners can publish their trained model and its ZKP verifier to Ethereum. Any user can claim an input (prompt) and publish the inference task, any node that maintains the model and the proving circuit can perform the inference and proving, then submit the output of inference and the ZK proof for the inference trace into the verifier that is deployed by the model owner. The user that initiates the inference task will own the output for the inference of that model and input (prompt).

In the opML scenario, model owners can publish their trained model and the model's final inference state to Ethereum. Any user can challenge the model's final state within a predefined challenge period and submit fraud proof. If there is no dispute within the challenge period. The user can verify that he/she owns the output for the inference of that model and input (prompt).

## Specification

Expand Down Expand Up @@ -52,6 +57,7 @@ interface IERC7007 is IERC165, IERC721 {

/**
* @dev Mint token at `tokenId` given `prompt`, `aigcData`, `uri` and `proof`.
* @dev `proof` means that we input the zk proof when using zkML and byte zero when using opML as the verification method.
*
* Requirements:
* - `tokenId` must not exist.'
Expand Down Expand Up @@ -133,6 +139,10 @@ ERC-7007 Metadata JSON Schema for reference
"aigc_data": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this AIGC NFT represents."
},
"verificaton": {
"type": "string",
"description": "Specify the verification method. Input zkML or opML."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense. want to propose another possible wording:
"proof_type": {
"type": "validity" / "fraud",
...
}
the point here is to align with "aigc_type".
we can discuss this.

}
}
}
Expand Down
79 changes: 79 additions & 0 deletions assets/erc-7007/contracts/ERC7007_opml.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "./IERC7007.sol";
import "./IOpmlLib.sol";

/**
* @dev Implementation of the {IERC7007} interface.
*/
contract ERC7007_opml is ERC165, IERC7007, ERC721URIStorage {
address public immutable opmlLib;
mapping(uint256 => uint256) tokenIdToRequestId;

/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(
string memory name_,
string memory symbol_,
address opmlLib_
) ERC721(name_, symbol_) {
opmlLib = opmlLib_;
}

/**
* @dev See {IERC7007-mint}.
*/
function mint(
bytes calldata prompt,
bytes calldata aigcData,
string calldata uri,
bytes calldata proof
) public virtual override returns (uint256 tokenId) {
tokenId = uint256(keccak256(prompt));
_safeMint(msg.sender, tokenId);
string memory tokenUri = string(
abi.encodePacked(
"{",
uri,
', "prompt": "',
string(prompt),
'", "aigc_data": "',
string(aigcData),
'"}'
)
);
_setTokenURI(tokenId, tokenUri);
tokenIdToRequestId[tokenId] = IOpmlLib(opmlLib).initOpmlRequest(prompt);
IOpmlLib(opmlLib).uploadResult(tokenIdToRequestId[tokenId], aigcData);

emit Mint(tokenId, prompt, aigcData, uri, proof);
}

/**
* @dev See {IERC7007-verify}.
*/
function verify(
bytes calldata prompt,
bytes calldata aigcData,
bytes calldata proof
) public view virtual override returns (bool success) {
uint256 tokenId = uint256(keccak256(prompt));
bytes32 output = bytes32(IOpmlLib(opmlLib).getOutput(tokenIdToRequestId[tokenId]));
return IOpmlLib(opmlLib).isFinalized(tokenIdToRequestId[tokenId]) && (output == keccak256(aigcData));
}

/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC165, IERC165, ERC721URIStorage) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
super.supportsInterface(interfaceId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import "./IVerifier.sol";
/**
* @dev Implementation of the {IERC7007} interface.
*/
contract ERC7007 is ERC165, IERC7007, ERC721URIStorage {
contract ERC7007_zkml is ERC165, IERC7007, ERC721URIStorage {
address public immutable verifier;

/**
Expand Down
13 changes: 13 additions & 0 deletions assets/erc-7007/contracts/IOpmlLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

interface IOpmlLib {
function initOpmlRequest(bytes calldata input) external returns (uint256 requestId); // we can construct the initialState using the input, can replace input with prompt (string)
function uploadResult(uint256 requestId, bytes calldata output) external;
function startChallenge(uint256 requestId, bytes32 finalState) external returns (uint256 challengeId);
function respondState(uint256 challengeId, bytes32 stateHash) external;
function proposeState(uint256 challengeId, bytes32 stateHash) external;
function assertStateTransition(uint256 challengeId) external;
function isFinalized(uint256 requestId) external view returns (bool);
function getOutput(uint256 requestId) external view returns (bytes memory output);
}