> For the complete documentation index, see [llms.txt](https://relationlabs.gitbook.io/protocol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://relationlabs.gitbook.io/protocol/protocol-zh/contract-open-standard/publication/privacy.md).

# 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"
    }
  }
]
```
