# 整体结构设计

## 整体架构

Relation Labs 基于SBT的理念，设计并实现了一套链上语义存储网络。通过该网络，各项目方和WEB3 开发者可以快速便捷地铸造语义SBT、建立自己的品牌，共同创建去中心化的社交图谱。该网络主要由三部分组成：

* 调用层
* 合约层
* 链外服务层

<figure><img src="https://1582633783-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1QTBCEp9cHDbxtcgpukV%2Fuploads%2Fgit-blob-0bfbcf8cb479fe73bdbaa9c5b8950cfa313e6dc5%2F%E6%B5%81%E7%A8%8B%E5%9B%BE%20(2).jpg?alt=media" alt=""><figcaption></figcaption></figure>

项目方或WEB3开发者在使用该语义网络时，首先需要将数据的schema保存在IPFS、Arweave 之类的链外去中心化存储服务器中，供后续数据组装和分析时使用。然后调用Semantic 合约进行数据的链上存储以及mint SBT等操作。同时结合着合约规范中的event事件，Semantic Scan会将SBT数据以RDF格式保存至包含Relation Graph的Semantic Scan中，并提供相应API接口，供项目方和开发者使用。同时也可以通过SPARQL进行相关数据的各种组合、关联等高级业务查询。

### 调用层

RDF作为资源描述框架，其本质是一个数据模型，是对具体事物的描述。但是RDF的表达能力有限，无法区分类和对象，也无法定义和描述类的关系或者属性。因此调用方在存储RDF数据前，需要先把数据对应的schema确定好，schema是RDF的属性描述，类比于数据库中的表结构。通过schema，开发者可以将保存至链上的数据形具有业务意义的数据。所以开发者在调用合约之前，需要先在链外定义好RDF Schema，并将其保存至IPFS、Arweave 之类的链外去中心化存储服务中。

下边是以“员工”为对象的RDF 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#>

### 这里定义了“员工”这个类
:Staff a rdfs:Class;
      rdfs:label "entity";
      rdfs:comment "A staff" .

### staff 有三个属性分别是name，age，career，对应类型分别是string，integer，string
p:name rdf:Property;
      rdfs:label "the name of staff";
      rdfs:range xsd:string .

p:age rdf:Property;
      rdfs:label "the age of staff";
      rdfs:range xsd:integer .
        
p:career rdf:Property;
      rdfs:label "the career of staff";
      rdfs:range xsd:string .
```

### 合约层

#### 合约逻辑设计

Semantic SBT合约在ERC721和ERC5192基础上，增加了RDF数据结构以及对应的生成方法。合约实现的逻辑设计方面主要分为三部分：

* Data Entity：定义了Class（主语实体）、Subject（主语）、Predicate（谓语）、Turtle（完整三元组） 等数据对象规范。通过数据实体规范了RDF数据组成单元。
* Semantic Entity：基于语义规范，对数据对象进行实例化和关系化组合，形成具体的RDF数据模型。
* Contract Method：在Semantic合约中，在数据规范和数据组装模型的前提下，定义了相应的方法，来完成SBT的创建和使用。

<figure><img src="https://1582633783-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1QTBCEp9cHDbxtcgpukV%2Fuploads%2FvxkYL2DB2idE9VryKVzk%2F%E5%90%88%E7%BA%A6%E9%80%BB%E8%BE%91%E5%AE%9E%E7%8E%B0.jpg?alt=media&#x26;token=4c5ca4af-79ff-4619-ad98-58be8ad8ca0b" alt=""><figcaption></figcaption></figure>

在这个三部分中，语义实体的实例化和组装起到关键性的作用，即关系到了数据的保存方式，有直接影响了SBT的生成过程。

#### 语义实体的生成逻辑

<figure><img src="https://1582633783-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1QTBCEp9cHDbxtcgpukV%2Fuploads%2FRnYnlY2PeEaZYgKHJHEc%2FUML%20%E5%9B%BE%20(1).jpg?alt=media&#x26;token=12a1501a-7203-4e9b-9399-fc05b1b05e46" alt=""><figcaption></figcaption></figure>

语义的组装过程主要包括以下几个步骤

* 初始化合约：在`合约初始化`阶段
  * 定义token的基本属性，比如token的name, symbol, baseURI
  * 定义主语对应的实例，即Class
  * 定义谓语，即Predicate
  * 定义SBT对应的schemaURI，用于保存RDF数据对应的schema
* 新增Subject：在`合约初始化`完成后，可以基于已经确定的Class，可以新建对应的主语。
* 新增Object：在`Mint`前，可以提前将需要新增的Object和已确定的Predicate关联生成相应的PredicateAndObject对象。
* 生成Turtle：在`Mint`过程中，将传入的Subject和PredicateAndObject组装为Turtle数据，生成对应Token，并分配给对应Address。
* 生成RDF数据：在`Mint` 结束前，通过事件通知方法，将Turtle数据转换为RDF格式的数据通知到合约监听方。

可以看出，在SBT的Mint过程中，Turtle的组装、创建和分发是SBT非常关键的部分。

#### **Turtle组成结构**

<figure><img src="https://1582633783-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1QTBCEp9cHDbxtcgpukV%2Fuploads%2FysHCsUGQAXLuCcnFEFGo%2FUML%20%E5%9B%BE%20(2).jpg?alt=media&#x26;token=35952ebb-90db-4926-9cb1-89442b996a6d" alt=""><figcaption></figcaption></figure>

1. 初始化合约时，会将主语对象和谓词提前制定好。在合约部署后的初始化阶段，会定义Class 和Predicate。初始化时，合约会基于 Class Name生成对应的Class的index。同样的，会基于Predicate Name 以及Predicate Type，生成对应的Predicate Index。谓词类型包括：Integer、String、Address、Subject和BlankNode。Subject可以理解为自定义谓词。
2. 创建主语，即Subject。Subject由Value和ClassId组成，在创建Subject时，通过addSubject方法，传入Subject Value 和Class Name，首先根据Class Name检查是否为初始化生成的Class，然后基于Subject Value生成对应的Subject Index，最后根据Class Index和Subject Value生成Subject。
3. 绑定谓词和宾语，即PredicateId和Object，生成PredicateAndObject。在mint Semantic Token 过程中，通过传入Predicate Index 和Object，生成对应Predicate类型的PredicateAndObject。
4. 将subject和predicateAndObject组装成Turtle，在mint Semantic Token 过程中，通过将Subject 和 PredicateAndObject关联，形成Turtle数据，并与对应的Token id相关联，并将Token指定给对应用户，该用户可以是合约调用者，也可以是指定SBT拥有者。
5. 将subject和predicateAndObject规范为RDF格式存储。通过合约事件监听，可以获取到组装好的RDF格式的数据，并可以将其直接进行链外数据保存。

### 链外服务层

链外服务层主要是通过合约监听服务将数据保存至图数据库中，进而可以通过图数据库进行业务功能扩展。具体的图数据库、合约监听服务，项目方可以根据自身技术架构自行选择和实现。

我们将在`使用The Graph 索引脸上RDF数据` 章节提供相应的实现Demo。

\`\`


---

# 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/semantic-sbt/semanticsbt-zh/zheng-ti-jie-gou-she-ji.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.
