# Privacy Content

基于Semantic SBT和[Lit Protocol](https://developer.litprotocol.com/sdk/explanation/encryption/#encrypting)实现隐私数据分享，用户可以给满足指定条件的地址分享自己的隐私数据。

使用Lit Protocol对数据进行加密与解密，[Arweave](https://www.arweave.org/)存储密文、加密后的密钥以及分享条件，Semantic SBT用于存储arweave的哈希以及定义分享条件。

分享的条件可以设置成：

* EOA地址
* 拥有特定集合NFT的用户
* 拥有特定SBT的用户
* 拥有一定 ERC20 代币余额的用户

## Schema

隐私数据分享的[schema模版](https://arweave.net/DeM6LRONjAUYr3qixkguLuFvYSHkykN7ZRKHn2HR5Gs)，schema以ttl文件的形式保存至Arweave，交易哈希将作为schemaURI，在初始化合约时传入，参数示例：

```
ar://DeM6LRONjAUYr3qixkguLuFvYSHkykN7ZRKHn2HR5Gs
```

schema由以下三部分组成：

* schema 前缀列表

```
PREFIX : <http://relationlabs.ai/entity/>
PREFIX p: <http://relationlabs.ai/property/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
```

* Class

Soul用于表示地址实体

```
:Soul a rdfs:Class ;
    rdfs:label "Soul" ;
    rdfs:comment "A soul." .
```

* Predicate

谓词`p:privacyData`表述隐私数据

```
p:privacyContent a rdf:Property ;
    rdfs:label "privacyContent" ;
    rdfs:comment "The privacy content." ;
    rdfs:domain :Soul ;
    rdfs:range xsd:string .
```

## 合约

```solidity
interface IPrivacyContent is ISemanticSBT {

    /**
     * 预生成tokenId
     * @return tokenId 预生成的tokenId
     */
    function prepareToken() external returns (uint256);
    /**
     * 查询持有的预生成tokenId
     * @param owner 被查询的地址
     * @return tokenId 预生成的tokenId
     */
    function ownedPrepareToken(address owner) external view returns (uint256);
    /**
     * 发布内容
     * @param content 发布的内容对应的Arweave交易哈希，可通过此交易哈希访问到原始发布内容
     */
    function post(string memory content) external;
    /**
     * 是否具备token的查看权限
     * @param viewer 查看者的地址
     * @param tokenId 发布的内容对应tokenId
     * @param isViewer true--具备查看权限；false--不具备查看权限
     */
    function isViewerOf(address viewer, uint256 tokenId) external view returns (bool);
    /**
     * 查询发布内容
     * @param tokenId
     * @return content 发布的内容对应的Arweave交易哈希，可通过此交易哈希访问到原始发布内容
     */
    function contentOf(uint256 tokenId) external view returns (string memory);
}

```

完整的实现合约代码可访问：

* [PrivacyContent](https://github.com/relationlabs/semanticSBT/blob/main/contracts/template/PrivacyContent.sol)

## 隐私数据分享流程

### 加密

将待分享的隐私数据，通过[Lit Protocol](https://developer.litprotocol.com/sdk/explanation/encryption/#encrypting)进行加密，并将加密结果（accessCondition、encryptedSymmetricKey、encryptedObject）封装成encryptMetaDada上传至存储层(arweave等)，得到encryptMetaDada的地址。

* encryptMetaDada格式如下：

```json
{
  "encryptionBy": "lit-protocol",
  "accessCondition": [
    {
      "contractAddress": "${contract address of Semantic SBT}",
      "standardContractType": "ERC721",
      "chain": "polygon",
      "method": "isViewerOf",
      "parameters": [
        ":userAddress",
        "${tokenId}"
      ],
      "returnValueTest": {
        "comparator": "=",
        "value": true
      }
    }
  ],
  "encryptedSymmetricKey": "a hex string that LIT will use to decrypt your content as long as you satisfy the conditions",
  // encrypted content
  "encryptedObject": "AhgXUao1QU2iQg34UsCw0-ptkoy_fhifEoqEs3_Zj1s="
}

```

### Mint隐私SBT

基于Semantic SBT规范实现一个PrivacySemanticSBT合约，mint一个带隐私数据的SBT。其中该SBT的RDF中的object为arweave/ipfs的地址。

* SemanticSBTPrivacy合约方法调用流程

```javascript
import {ethers, providers} from 'ethers'

const accounts = await ethereum.request({method: 'eth_requestAccounts'})

await PrivacySemanticSBT.prepareTokenId();
const tokenId = await PrivacySemanticSBT.ownedPrepareToken(accounts[0]);
//Mint SBT
PrivacySemanticSBT.mintWithPrivacy(tokenId, arweaveHash);
//添加viewer
await PrivacySemanticSBT.addViewer(address1, tokenId);
```

* 完整的RDF示例如下：

```
:Soul_0x0000000000000000000000000000000000000000 p:privacyContent "ar://djbZ5l5Ij5zBEgFFnVlDDqa4z5ACtS_A9uWPmAVwRe"
```

* encryptedObject的组成
  * web3存储系统，比如: `ar://` 或 `ipfs://`
  * web3存储的哈希
* encryptedObject示例：

```
ar://djbZ5l5Ij5zBEgFFnVlDDqa4z5ACtS_A9uWPmAVwRe
```

### 解密

解密方从SBT的object中获取encryptMetaDada。调用[LitProtocol的解密方法](https://developer.litprotocol.com/sdk/explanation/encryption/#decrypting)，即可解密得到明文的object。

## AccessConditions

允许设置不同类型的访问条件，来控制用户访问隐私数据。

### 用户拥有特定的钱包地址

如果解密者拥有指定的钱包地址，则有权限解密隐私数据。

```
[
  {
    "contractAddress": "",
    "standardContractType": "",
    "chain": "ethereum",
    "method": "",
    "parameters": [
      ":userAddress",
    ],
    "returnValueTest": {
      "comparator": "=",
      "value": "0x50e2dac5e78B5905CB09495547452cEE64426db2"
    }
  }
]
```

### 用户持有NFT集合的token

如果解密者拥有指定NFT集合的token，则有权限解密隐私数据。

```
[
  {
    "contractAddress": "0x3110c39b428221012934A7F617913b095BC1078C",
    "standardContractType": "ERC721",
    "chain": "ethereum",
    "method": "balanceOf",
    "parameters": [ ":userAddress" ],
    "returnValueTest": { "comparator": ">", "value": "0" }
  }
]
```

#### 用户持有NFT集合的Token

如果解密者拥有指定SBT集合的token，则有权限解密隐私数据。

```
[
  {
    "contractAddress": "0x588368698213bdf05aa722936d7657df8f3abe27",
    "standardContractType": "ERC721",
    "chain": "polygon",
    "method": "balanceOf",
    "parameters": [ ":userAddress" ],
    "returnValueTest": { "comparator": ">", "value": "0" }
  }
]
```

### 用户持有至少XX个ERC20 Token

如果解密者拥有指定数量的ERC20token，则有权限解密隐私数据。

```
[
  {
    "contractAddress": "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2",
    "standardContractType": "ERC20",
    "chain": "ethereum",
    "method": "balanceOf",
    "parameters": [
      ":userAddress"
    ],
    "returnValueTest": {
      "comparator": ">",
      "value": "0"
    }
  }
]
```

### 可以使用AND或OR任意组合上述条件

```json
[
  {
    "contractAddress": "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2",
    "standardContractType": "ERC20",
    "chain": "ethereum",
    "method": "balanceOf",
    "parameters": [
      ":userAddress"
    ],
    "returnValueTest": {
      "comparator": ">",
      "value": "0"
    }
  },
  {
    "operator": "or"
  },
  {
    "contractAddress": "0x3110c39b428221012934A7F617913b095BC1078C",
    "standardContractType": "ERC721",
    "chain": "ethereum",
    "method": "balanceOf",
    "parameters": [
      ":userAddress"
    ],
    "returnValueTest": {
      "comparator": ">",
      "value": "0"
    }
  }
]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://relationlabs.gitbook.io/protocol/protocol-zh/contract-open-standard/publication/privacy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
