Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Fix typos #107

Merged
merged 4 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ _Pessimism_ is a public good monitoring service that allows for [Op-Stack](https
Pessimism is currently experimental and very much in development. It means Pessimism is currently unstable, so code will change and builds can break over the coming months. If you come across problems, it would help greatly to open issues so that we can fix them as quickly as possible.

## Setup
To use the template, run the following the command(s):
To use the template, run the following command(s):
1. Create local config file (`config.env`) to store all necessary environmental variables. There's already an example `config.env.template` in the repo that stores default env vars.

2. [Download](https://go.dev/doc/install) or upgrade to `golang 1.19`.
Expand All @@ -44,14 +44,14 @@ It can be ran using the following project level command(s):
## Testing

### Unit Tests
Unit tests are written using the native [go test](https://pkg.go.dev/testing) library with test mocks generated using the golang native [mock](https://github.com/golang/mock) library. These tests live throughout the the project's `/internal` directory and are named with the suffix `_test.go`.
Unit tests are written using the native [go test](https://pkg.go.dev/testing) library with test mocks generated using the golang native [mock](https://github.com/golang/mock) library. These tests live throughout the project's `/internal` directory and are named with the suffix `_test.go`.

Unit tests can run using the following project level command(s):
* Using Make: `make test`
* Direct Call: `go test ./...`

### Integration Tests
Integration tests are written that leverage the existing [op-e2e](https://github.com/ethereum-optimism/optimism/tree/develop/op-e2e) testing framwork for spinning up pieces of the bedrock system. Additionally, the [httptest](https://pkg.go.dev/net/http/httptest) library is used to mock downstream alerting services (e.g. Slack's webhook API). These tests live in the project's `/e2e` directory.
Integration tests are written that leverage the existing [op-e2e](https://github.com/ethereum-optimism/optimism/tree/develop/op-e2e) testing framework for spinning up pieces of the bedrock system. Additionally, the [httptest](https://pkg.go.dev/net/http/httptest) library is used to mock downstream alerting services (e.g. Slack's webhook API). These tests live in the project's `/e2e` directory.

Integration tests can run using the following project level command(s):
* Using Make: `make e2e-test`
Expand Down Expand Up @@ -92,4 +92,4 @@ A bootstrap config file is used to define the initial state of the pessimism ser


## Spawning an invariant session
To learn about the currently supported invariants and how to spawn them, please advise the [invariants' documentation](./docs/invariants.md).
To learn about the currently supported invariants and how to spawn them, please advise the [invariants' documentation](./docs/invariants.md).
10 changes: 5 additions & 5 deletions docs/engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ graph LR;
The ETL publishes `Invariant Input` to the Risk Engine using a relay channel. The Risk Engine will subscribe to this channel to receive and process updates as they are published by the ETL. The Risk Engine will also publish events to the Alerting system using a separate downstream relay channel. The Alerting system will subscribe to this channel to receive and process updates as they are published by the Risk Engine.

## Invariant Session
An invariant session refers the the execution and representation of a single invariant. An invariant session is uniquely identified by a `SUUID` and is associated with a single `PUUID`. An invariant session is created by the `EngineManager` when a user requests to run an active session. The `EngineManager` will create a new `InvariantSession` and pass it to the `RiskEngine` to be executed. The `RiskEngine` will then execute the invariant session and return an `InvalidationOutcome` to the `EngineManager`. The `EngineManager` will then create an `Alert` using the `InvalidationOutcome` and publish it to the Alerting system.
An invariant session refers to the execution and representation of a single invariant. An invariant session is uniquely identified by a `SUUID` and is associated with a single `PUUID`. An invariant session is created by the `EngineManager` when a user requests to run an active session. The `EngineManager` will create a new `InvariantSession` and pass it to the `RiskEngine` to be executed. The `RiskEngine` will then execute the invariant session and return an `InvalidationOutcome` to the `EngineManager`. The `EngineManager` will then create an `Alert` using the `InvalidationOutcome` and publish it to the Alerting system.

## Session UUID (SUUID)
The SUUID is a unique identifier that is used to identify a specific invariant session. The SUUID is generated by the `EngineManager` when a user requests to run a new invariant session. The SUUID is used to uniquely identify a specific invariant session. This allows the `EngineManager` to perform operations on a specific invariant session such as removing it or updating it.
Expand All @@ -52,7 +52,7 @@ The invariant input is a struct that contains the following fields:
* `Input` - Transit data that was generated by the ETL

## Invariant
An invariant is a logical execution module that defines some set of invalidation criteria. The invariant is responsible for processing the input data and determining if an invalidation has occured. If an invalidation has occured, the invariant will return a `InvalidationOutcome` that contains relevant metadata necessary for the `EngineManager` to create an `Alert`.
An invariant is a logical execution module that defines some set of invalidation criteria. The invariant is responsible for processing the input data and determining if an invalidation has occurred. If an invalidation has occurred, the invariant will return a `InvalidationOutcome` that contains relevant metadata necessary for the `EngineManager` to create an `Alert`.

### Hardcoded Base Invariant
Every hardcoded invariant must implement an `Invariant` interface to be compatible for invalidation by the `Hardcoded` Risk Engine type. Currently the interface is as follows:
Expand All @@ -71,7 +71,7 @@ type Invariant interface {
The invariant input type is a `RegisterType` that defines the type of data that the invariant will receive as input. The invariant input type is defined by the `InputType()` method of the `Invariant` interface. The invariant input type is used by the `RiskEngine` to determine if the input data is compatible with the invariant. If the input data is not compatible with the invariant, the `RiskEngine` will not execute the invariant and will return an error.

### Addressing
All invariants have a boolean propety `Addressing` which determines if the invariant is addressable. To be addressable, an invariant must only execute under the context of a single address.
All invariants have a boolean property `Addressing` which determines if the invariant is addressable. To be addressable, an invariant must only execute under the context of a single address.

For example, a `balance_enforcement` invariant session will be addressable because it only executes invalidation logic for the native ETH balance of a single address.

Expand All @@ -93,11 +93,11 @@ As of now, there are two types of hardcoded invariants that a user can deploy ac
- `balance_enforcement` - Invariant that checks an address's balance changes and ensures that the balance does not exceed a certain threshold

### How to add a new invariant
1. Create a new file in the `internal/engine/registry` directory that stores the invariant implementaion. The implementation must adhere to the interface specified for the `BaseInvariant` type.
1. Create a new file in the `internal/engine/registry` directory that stores the invariant implementation. The implementation must adhere to the interface specified for the `BaseInvariant` type.

3. Add a new entry to the `InvariantType` enum in `internal/core/constants.go`
2. Add a new entry to the registry in `internal/engine/registry/registry.go`

## Dynamic Invariant Types
**Not currently supported**
Dynamic invariants are programmable entities that can be deployed as arbitrary code by a user. They are represented via some code standard that is dynamically executable by a Risk Engine. Unlike `Hardcoded` invariants, dynamic invariants can be deployed and executed without modifying the source code of the Pessimism application.
Dynamic invariants are programmable entities that can be deployed as arbitrary code by a user. They are represented via some code standard that is dynamically executable by a Risk Engine. Unlike `Hardcoded` invariants, dynamic invariants can be deployed and executed without modifying the source code of the Pessimism application.
14 changes: 7 additions & 7 deletions docs/etl.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Aggregators are used to solve the problem where a pipe or an invariant input wil

#### Attributes
* Able to read heterogenous transit data from an arbitrary number of component ingresses
* A synchronization policy that defines how different transit data from multiple ingress streams will be aggregated into a collectivly bound single piece of data
* A synchronization policy that defines how different transit data from multiple ingress streams will be aggregated into a collectively bound single piece of data
* EgressHandler to handle downstream transit data routing to other components or destinations

#### Single Value Subscription
Expand All @@ -120,7 +120,7 @@ Single Value Subscription refers to a synchronization policy where a bucketed mu

For example we can have an invariant that subscribes to blocks from two heterogenous chains (layer1, layer2) or `{ChainA, ChainB}`, let's assume `BLOCK_TIME(ChainA) > BLOCK_TIME(ChainB)`.

We can either specify that the invariant will run every-time there's an update or a new block from `ChainA`:
We can either specify that the invariant will run every time there's an update or a new block from `ChainA`:
```
{
"A:latest_blocks": [xi] where cardinality = 1,
Expand Down Expand Up @@ -184,15 +184,15 @@ graph LR;
A `GethBlock` register refers to a block output extracted from a go-ethereum node. This register is used for creating `Oracle` components that poll and extract block data from a go-ethereum node in real-time.

### Geth Account Balance Oracle Register
An `AccountBalance` register refers to a native ETH balance output extracted from a go-ethereum node. This register is used for creating `Oracle` components that poll and extract native ETH balance data for some state persisted addreses from a go-ethereum node in real-time.
An `AccountBalance` register refers to a native ETH balance output extracted from a go-ethereum node. This register is used for creating `Oracle` components that poll and extract native ETH balance data for some state persisted addresses from a go-ethereum node in real-time.
Unlike, the `GethBlock` register, this register requires knowledge of an address set that's shared with the risk engine to properly function and is therefore addressable. Because of this, any invariant that uses this register must also be addressable.

## Managed ETL

### Component Graph
The ETL uses a `ComponentGraph` construct to represent and store critical component inter-connectivity data _(ie. component node entries and graph edges)_.

A graph edge is represented as a binded communication path between two arbitrary component nodes (`c1`, `c2`). Adding an edge from some component (`c1`) to some downstream component (`c2`) results in `c1` having a path to the ingress of `c2` in it's [egress handler](#egress-handler). This would look something like:
A graph edge is represented as a binded communication path between two arbitrary component nodes (`c1`, `c2`). Adding an edge from some component (`c1`) to some downstream component (`c2`) results in `c1` having a path to the ingress of `c2` in its [egress handler](#egress-handler). This would look something like:

```mermaid
graph TB;
Expand Down Expand Up @@ -220,11 +220,11 @@ graph TB;
Pipelines are used to represent some full component path in a DAG based `ComponentGraph`. A pipeline is a sequence of components that are connected together in a way to express meaningful ETL operations for extracting some invariant input for consumption by the Risk Engine.

### Pipeline States
- `Backfill` - Backfill denotes that the pipeline is currently performing a backfill operation. This means the pipeline is sequentially reading data from some starting height to the most recent block height. This is useful for building state dependendent pipelines that require some knowledge of prior history to make live assessments. For example, detecting imbalances between the native ETH deposit supply on the L1 portal contract and the TVL unlocked on the L2 chain would require indexing the prior history of L1 deposits to construct correct supply values.
- `Backfill` - Backfill denotes that the pipeline is currently performing a backfill operation. This means the pipeline is sequentially reading data from some starting height to the most recent block height. This is useful for building state dependent pipelines that require some knowledge of prior history to make live assessments. For example, detecting imbalances between the native ETH deposit supply on the L1 portal contract and the TVL unlocked on the L2 chain would require indexing the prior history of L1 deposits to construct correct supply values.
- `Live` - Live denotes that the pipeline is currently performing live operations. This means the pipeline is reading data from the most recent block height.
- `Stopped` - Stopped denotes that the pipeline is currently not performing any operations. This means the pipeline is neither reading nor processing any data.
- `Paused` - Paused denotes that the pipeline is currently not performing any operations. This means the pipeline is neither reading nor processing any data. The difference between `Stopped` and `Paused` is that a `Paused` pipeline can be resumed at any time while a `Stopped` pipeline must be restarted.
- `Error` - Error denotes that the pipeline is currently in an error state. This means the pipeline is neither reading nor processing any data. The difference between `Stopped` and `Error` is that a `Error` pipeline can be resumed at any time while a `Stopped` pipeline must be restarted.
- `Error` - Error denotes that the pipeline is currently in an error state. This means the pipeline is neither reading nor processing any data. The difference between `Stopped` and `Error` is that an `Error` pipeline can be resumed at any time while a `Stopped` pipeline must be restarted.

### Pipeline Types
There are two types of pipelines:
Expand All @@ -242,7 +242,7 @@ All pipelines have a PUUID that stores critical identification data. Pipeline UU
* Route invariant inputs between the ETL and Risk Engine
* Understand when pipeline collisions between `PIDs` occur

Pipeline UUID's constitute of both a randomly generated `UUID` and a deterministic `PID`. This is done to ensure uniqueness of each component instance while also ensuring collision based properties so that overlaping components can be deduplicated when viable.
Pipeline UUID's constitute of both a randomly generated `UUID` and a deterministic `PID`. This is done to ensure uniqueness of each component instance while also ensuring collision based properties so that overlapping components can be deduplicated when viable.

A `PipelinePID` is encoded using the following 9 byte array sequence:
```
Expand Down