# 事件日志

#### 事件日志

Ceramic协议中的核心数据结构是自认证事件日志。它将IPLD哈希链接数据和加密证明相结合，创建了一个经过身份验证且不可变的日志。这个事件日志可以用来建模可变数据库和其他数据结构。

## **介绍**

只追加日志在分布式系统中经常被用作的底层不可变数据结构，来提升数据的完整性、一致性、性能表现和历史记录等方面。开放式分布式系统使用哈希链接列表/日志来允许其他人验证任何数据的完整性。IPLD 提供了一种自然的方法来定义一个不可变的只追加日志。

* **Web3 认证** - 当与密码签名和区块链时间戳结合使用时，它允许使用区块链账户和 DIDs 对这些日志进行身份验证写入。
* **低成本去中心化** - 为用户和应用程序提供一个共同的数据库层，而不是更昂贵的 on-chain 数据或集中且孤立的数据库。
* **互操作性、灵活性、组合能力** - 最小限度定义的日志结构允许在保持多样化实现可变数据库和数据结构基础上具有基本的互操作性。基本水平互操作包括日志传输、更新同步、共识等。

## **事件**

日志由事件组成。初始化事件会创建一个新的日志，并用于引用或命名日志。流的名称称为[StreamId](https://developers.ceramic.network/protocol/streams/uri-scheme/#streamid)。每个增加的“更新”都作为数据事件追加到其中。定期地，时间事件在一个或多个数据事件之后会被添加。**时间事件**允许你使用区块链时间戳证明某个事件在某个时间点之前发布过。它们还可用于对流中的事件进行排序以及跨流和区块链事件进行全局排序。此处提供了日志最小定义，头部和正文中的其他参数由应用程序级别或更高级别协议定义。**数据事件**（通常包括Init Events）是签名DAGJWS并使用[DAG-JOSE](https://ipld.io/specs/codecs/dag-jose/spec/)编解码器编码为IPLD格式的内容。 通常情况下，Event负载被编码为DAG-CBOR，但可以使用节点或网络支持的任何编解码器进行编码处理 。 格式和类型使用[IPLD模式语言](https://ipld.io/docs/schemas/)描述，并且以下进一步描述了Event编码。

### **初始化事件 InitEvent**

日志通过初始化事件进行初始化。此事件的CID用于在[StreamId](https://developers.ceramic.network/protocol/streams/uri-scheme/#streamid)中引用或命名此日志。初始化事件可以签名或未签名。

```Plaintext
type InitHeader struct {
  controllers [String]
}
type InitPayload struct {
  header InitHeader
  data optional Any 
}

type InitJWS struct { // This is a DagJWS
  payload String
  signatures [Signature]
  link: &InitPayload
}

type InitEvent InitPayload | InitJWS
```

**Parameters defined as follows:**&#x53C2;数定义如下：

* **controllers** - 一串DID字符串数组，用于定义哪些DID可以将事件写入日志。当使用CACAO时，预期的DID是CACAO的发行者。**目前仅支持单个DID**。
* **data** - 数据可以是任何内容。如果已定义，则Init Event必须与InitJWS结构或信封匹配，并以**DAG-JOSE**编码；否则，InitPayload本身将是有效的init event，并以DAG-CBOR编码。

### **数据事件 DataEvent**

日志更新是数据事件。数据事件被附加在初始化事件、先前的数据事件或时间事件之后。必须对数据事件进行**签名**。

<pre class="language-Plaintext"><code class="lang-Plaintext">type Event InitEvent | DataEvent | TimeEvent

type DataHeader struct {
  controllers optional [String]
}

type DataEventPayload struct {
  id &#x26;InitEvent
<strong>  prev &#x26;Event
</strong>  header optional DataHeader
  data Any 
}

type DataEvent struct { // This is a DagJWS
  payload String
  signatures [Signature]
  link: &#x26;DataEventPayload
}
</code></pre>

附加参数定义如下，控制器和数据与上述相同。**id** - 日志初始化事件的CID（链接）**prev** - 日志中先前事件的CID（链接）**header** - 可选标题，仅在从先前事件更改标题参数值（控制器）时包含在此处。其他标题值可以包含在此规范之外。这是关于IPLD最小定义的日志，稍后的规范或协议可以根据需要向init和data事件及其标头添加其他参数。

### **时间事件 TimeEvent**

时间事件可以附加到初始事件和1个或多个数据事件。有关创建和验证时间事件的详细信息，请参考[CAIP-168 IPLD 时间戳](https://chainagnostic.org/CAIPs/caip-168)证明规范。时间事件是IPLD 时间戳证明规范的简单扩展，其中prev指向日志中先前的事件，并且预计是时间戳证明所用数据。时间戳事件未签名。

```Plaintext
type TimeEvent struct {
  id &InitEvent
  prev &DataEvent | &InitEvent
  proof Link
  path String
}
```

## **证明**

一个有效的日志是指包括上述定义的数据事件，并且遍历该日志会解析到上述定义的初始事件。当事件包含所需参数并且DAGJWS签名对于给定的事件控制器DID有效时，这个事件才是有效的。如下面所定义。时间事件由CAIP-168定义为有效。可能会有特定于任何协议或应用程序级别定义的其他验证步骤。

## **编码**

### **JWS & DAG-JOSE**

所有已签名的事件都使用[DAG-JOSE](https://ipld.io/specs/codecs/dag-jose/spec/)在IPLD中进行编码。 DAG-JOSE是一种编解码器和标准，用于在IPLD中对JOSE对象进行编码。 JOSE包括用于签名JSON对象的[JWS](https://datatracker.ietf.org/doc/rfc7515/?include_text=1)和用于加密JSON对象的[JWE](https://datatracker.ietf.org/doc/rfc7516/?include_text=1)。 这里使用JWS来处理事件，并且它通常被用作已签名数据负载的标准。 一些参数进一步为流定义了规范。 原始的DAG-JOSE规范可以在[此处](https://ipld.io/specs/codecs/dag-jose/spec/)找到。以下内容定义了一个通用的已签名事件，其中init和data事件以上更具体地定义了其含义。

```Plaintext
type Signature struct {
  header optional { String : Any }
  // The base64url encoded protected header, contains:
  // `kid` - the DID URL used to sign the JWS
  // `cap` - IPFS url of the CACAO used (optional)
  protected optional String
  signature String
}

type EventJWS struct {
  payload String
  signatures [Signature]
  link: &Event
}
```

其中：

* link - 此签名所覆盖的事件的CID（链接）。提供易于应用程序访问和IPLD遍历，预计与有效载荷中编码的CID匹配
* payload - base64url编码的CID链接到此签名所覆盖的事件（JWS负载）
* protected - base64编码的JWS受保护标头
* header - base64编码的JWS标头
* signature - base64编码的JWS签名
