# CIP-146: After

Author | Aaron Goldman, Mohsin Zaidi |
---|---|

Discussions-To | https://forum.ceramic.network/t/cip-146-after-discussion/1527 |

Status | Draft |

Category | Core |

Created | 2024-03-22 |

## Table of Contents

## Simple Summary

Allows Data Events to prove that they happened after an Ethereum block timestamp

## Abstract

This CIP adds the ability to more closely determine the time *after* which an Init or Data Event was added to a Ceramic
stream.

Currently, it is possible to determine the time *before* which a Data event was added by looking at the Time Event
corresponding to the Data Event. However, it is not possible to determine a specific time after which the event was
created.

## Motivation

Time is a useful dimension in which to express interests.

There are various circumstances in which a node might be interested in the most recent events for a model. Because the nature of Recon is to synchronize sets of data, it is important that multiple nodes can agree upon an identical ordering of events. We can’t use anchor time as the mutual timestamp because anchor time can change and two nodes might not agree on the same anchor time at the beginning of the sync.

By introducing “after” timestamps, every event will have an immutable time that it is after.

For example, at the streaming layer:

- A node may be interested in subscribing to a Metrics model in order to populate some dashboard but only cares about events from the last 30 days. By using the “after” timestamp, the node can request only events that occurred after the current time minus 30 days by expressing an interest that filters on “after > (now - 30 days)”. This will allow the node to sync only the events that it is interested in. Despite the fact that the number of streams and events for the Metrics model grows without bounds, the node only needs to allocate enough resources to sync the events from the time range it is interested in.
- A node operator might choose to split out the task of archiving older data to a different node. By using the “after” timestamp, the node operator can determine which events are older than a certain time and synchronize them separately from recent events.
- If an application is using a Service Announcement model for service discovery, we can imagine that the announcements are only meaningful for a few hours before becoming irrelevant. This forces service providers to make announcements at least every few hours, or their announcements will expire.

An example at the aggregation layer could be for an aggregator to use the “after” timestamp to determine the order of events in a stream in a Last-Writer-Wins (LWW) fashion. Rather than the current default diff-stream behavior where the last writer is rejected during conflict resolution, an aggregator could use the “after” timestamp to permit the LWW strategy that is the default for most traditional data storage solutions, like filesystems and databases.

## Specification

### Three Flavors of Time Proofs

All time proofs described below are stored as DAG-CBOR but are represented here as DAG-JSON.

#### Before

“Before” proofs are time proofs as they exist in the protocol today. A Before proof proves that a Data Event in the corresponding Merkle tree happened before the timestamp of the Ethereum block containing the transaction hash included in the proof.

Before proofs are pointed to by the `proof`

field of a Time Event.

```
{
"chainId": "eip155:1",
"root": { "/": "bafyreicbwzaiyg2l4uaw6zjds3xupqeyfq3nlb36xodusgn24ou3qvgy4e" },
"txHash": { "/": "bagjqcgzax554ofnatxvdc54gnlcpykkkzgaa5yvutye4kx2wa6cxtp536fma" },
"txType": "f(bytes32)"
}
```

#### After

“After” proofs are a new type of proof block proposed by this spec. An After proof proves that a Data Event happened after the timestamp of the Ethereum block whose block hash is included in the proof.

After proofs are pointed to by the `after`

field in the `header`

of a Data Event.

```
{
"chainId": "eip155:1",
"blkHash": { "/": "bagiacgzapa6nljx6xyj5bcwa2wp2pztgja6v4r3fikzjncfg6c7mhuk75pka" }
}
```

#### Ordered

An “Ordered” proof is a new type of proof block proposed by this spec. An Ordered proof proves both:

- A Data Event in the corresponding Merkle tree happened before the timestamp of the Ethereum block whose block hash is included in the proof.
- A Data Event with an
`after`

field pointing to this proof happened after the timestamp of the Ethereum block whose block hash is included in the proof.

Ordered proofs can be pointed to by the `proof`

field of a Time Event.

```
{
"chainId": "eip155:1",
"root": { "/": "bafyreicbwzaiyg2l4uaw6zjds3xupqeyfq3nlb36xodusgn24ou3qvgy4e" },
"txHash": { "/": "bagjqcgzax554ofnatxvdc54gnlcpykkkzgaa5yvutye4kx2wa6cxtp536fma" },
"txType": "f(bytes32)",
"blkHash": { "/": "bagiacgzapa6nljx6xyj5bcwa2wp2pztgja6v4r3fikzjncfg6c7mhuk75pka" }
}
```

### After in Data Event

The `header`

field of a Data Event shall include a new `after`

field that points to an After proof or an Ordered proof.

```
{
"data": {},
"header": {
"controllers": [
"did:key:z6MkhvoSQhPDNwotybwX9o2scoSvkx5Syem3GiM9FV8h5YXG"
],
"after": { "/": "bafyreidtsz24vstukaoxisgrpdjijgsof3u3ls5d22fcly2qcp6ksx4cfe" }
}
}
```

### After in Time Event

The `proof`

field of a Time Event can point to either a Before proof or an Ordered proof.

```
{
"id": { "/": "bagcqceraplay4erv6l32qrki522uhiz7rf46xccwniw7ypmvs3cvu2b3oulq" },
"path": "0/0/0/0/0/0/0/0/0/0",
"prev": { "/": "bagcqceraplay4erv6l32qrki522uhiz7rf46xccwniw7ypmvs3cvu2b3oulq" },
"proof": { "/": "bafyreidtsz24vstukaoxisgrpdjijgsof3u3ls5d22fcly2qcp6ksx4cfe" }
}
```

## Backwards Compatibility

Since this CIP only proposes adding new fields without removing or reinterpreting existing fields, this CIP is backwards compatible with the current protocol.

Any event that is created without an `after`

field will be considered to have happened on January 1, 1970, 00:00:00 UTC.

## Implementation

Implementation will need to cache the timestamps corresponding to the Ethereum block hashes in the After/Ordered proofs and the transaction hashes in the Before/Ordered proofs. Timestamps not already cached will need to be fetched from an Ethereum node.

Ceramic nodes should maintain the CID of the latest time proof so that they can provide it to clients for use in their Data Events.

## Security Considerations

Time assertions are only as good as the Ethereum timestamps.

## Copyright

Copyright and related rights waived via CC0.

## Citation

Please cite this document as:

Aaron Goldman, Mohsin Zaidi, "CIP-146: After [DRAFT]," *Ceramic Improvement Proposals*, no. 146, March 2024. [Online serial]. Available:
https://github.com/ceramicnetwork/CIPs/blob/main/CIPs/cip-146.md