diff --git a/Dockerfile b/Dockerfile index ff7f8376..d901394a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,4 +23,4 @@ EXPOSE 8080 EXPOSE 7300 # Run app -CMD ["./pessimism"] \ No newline at end of file +CMD ["./pessimism"] diff --git a/README.md b/README.md index 985caca9..8e9de813 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # pessimism __Because you can't always be optimistic__ -_Pessimism_ is a public good monitoring service that allows for [Op-Stack](https://stack.optimism.io/) and EVM compatible blockchains to be continuously assessed for real-time threats using custom defined user invariant rule sets. To learn about Pessimism's architecture, please advise the documentation. +_Pessimism_ is a public good monitoring service that allows for [OP Stack](https://stack.optimism.io/) and EVM compatible blockchains to be continuously assessed for real-time threats using custom defined user heuristic rule sets. To learn about Pessimism's architecture, please advise the documentation. @@ -53,7 +53,7 @@ To use the template, run the following command(s): docker run -p 8080:8080 -p 7300:7300 --env-file=config.env -it -v ${PWD}/genesis.json:/app/genesis.json ghcr.io/base-org/pessimism:latest ``` -**Note**: If you want to bootstrap the application and run specific invariants/pipelines upon start, update config.env `BOOTSTRAP_PATH` value to the location of your genesis.json file then run +**Note**: If you want to bootstrap the application and run specific heuristics/pipelines upon start, update config.env `BOOTSTRAP_PATH` value to the location of your genesis.json file then run ### Building and Running New Images - Run `make docker-build` at the root of the repository to build a new docker image. @@ -96,7 +96,7 @@ A bootstrap config file is used to define the initial state of the pessimism ser "type": "contract_event", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "address": "0xfC0157aA4F5DB7177830ACddB3D5a9BB5BE9cc5e", "args": ["Transfer(address, address, uint256)"] } @@ -107,7 +107,7 @@ A bootstrap config file is used to define the initial state of the pessimism ser "type": "balance_enforcement", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "address": "0xfC0157aA4F5DB7177830ACddB3D5a9BB5BE9cc5e", "lower": 1, "upper": 2 @@ -117,6 +117,5 @@ 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.markdown). +## Spawning a heuristic session +To learn about the currently supported heuristics and how to spawn them, please advise the [heuristics' documentation](./docs/heuristics.markdown). diff --git a/config.env.template b/config.env.template index f851ece1..9400a504 100644 --- a/config.env.template +++ b/config.env.template @@ -1,6 +1,6 @@ # GETH compliant RPC APIs for layer 1 & 2 blockchains -L1_RPC_ENDPOINT= -L2_RPC_ENDPOINT= +L1_RPC_ENDPOINT="" +L2_RPC_ENDPOINT="" # Oracle Geth Block Poll Intervals (ms) L1_POLL_INTERVAL=5000 @@ -15,7 +15,7 @@ BOOTSTRAP_PATH=genesis.json # Server configurations -SERVER_HOST=localhost +SERVER_HOST="localhost" SERVER_PORT=8080 SERVER_KEEP_ALIVE_TIME=10 SERVER_READ_TIMEOUT=10 @@ -23,11 +23,10 @@ SERVER_WRITE_TIMEOUT=10 SERVER_SHUTDOWN_TIME=10 # Output Configs -SLACK_ENDPOINT= -SLACK_CHANNEL= +SLACK_ENDPOINT="" # Metrics configurations -METRICS_HOST=localhost +METRICS_HOST="localhost" METRICS_PORT=7300 ENABLE_METRICS=1 # 0 to disable, 1 to enable METRICS_READ_HEADER_TIMEOUT=60 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..42d8e78f --- /dev/null +++ b/docs/README.md @@ -0,0 +1,52 @@ +# Pessimism Documentation + +This directory contains the english specs for the Pessimism application. + +## Contents +- [Architecture](architecture/architecture.markdown) +- [JSON-RPC API](swaggerdoc.html) +- [ETL Subsystem](architecture/etl.markdown) +- [Engine Subsystem](architecture/engine.markdown) +- [Alerting Subsystem](architecture/alerting.markdown) +- [Heuristics](heuristics.markdown) +- [Telemetry](telemetry.markdown) + +## GitHub Pages +The Pessimism documentation is hosted on GitHub Pages. To view the documentation, please visit [https://base-org.github.io/pessimism](https://base-org.github.io/pessimism/architecture). + + +## Contributing +If you would like to contribute to the Pessimism documentation, please advise the guidelines stipulated in the [CONTRIBUTING.md](../CONTRIBUTING.md) file __before__ submitting a pull request. + + +## Running Docs Website Locally + +### Prerequisites +- Ensure that you have installed the latest version of ruby on your machine following steps located [here](https://www.ruby-lang.org/en/documentation/installation/). +- Installing ruby should also install the ruby bundler which is used to install dependencies located in the [Gemfile](Gemfile) + +### Local Testing +To run the documentation website locally, ensure you have followed the prerequisite steps, then do the following +1. Install dependencies via `bundle install` +2. Run `bundle exec jekyll serve` +3. You should now see a localhost version of documentation for the website! + +## Creating Diagrams in GitHub Pages + +It is important to note that you cannot simply write a mermaid diagram as you normally would with markdown and expect the diagram to be properly rendered via GitHub pages. To enable proper GitHub pages rendering, follow the recommended steps below: +1. Implement your diagram in markdown using the ` ```mermaid\n` key +2. Once done with implementing the diagram, ff you have not already, import the mermaid.js library via the following + ``` + {% raw %} + + {% endraw %} + ``` +3. Delete the ` ```mermaid ` key and replace it with + ``` + {% raw %} +
+ --- diagram implementation here --- +
+ {% endraw %} + +4. Done! To make sure this renders correctly, you can run `bundle exec jekyll serve` to view your changes. \ No newline at end of file diff --git a/docs/architecture/alerting.markdown b/docs/architecture/alerting.markdown index 7bde3d63..400fc2b0 100644 --- a/docs/architecture/alerting.markdown +++ b/docs/architecture/alerting.markdown @@ -9,7 +9,7 @@ permalink: /architecture/alerting {% endraw %} ## Overview -The alerting subsystem will receive alerts from the `EngineManager` and publish them to the appropriate alerting destinations. The alerting subsystem will also be responsible for managing the lifecycle of alerts. This includes creating, updating, and removing alerting entries for invariant sessions. +The alerting subsystem will receive alerts from the `EngineManager` and publish them to the appropriate alerting destinations. The alerting subsystem will also be responsible for managing the lifecycle of alerts. This includes creating, updating, and removing alerting entries for heuristic sessions. ## Diagram @@ -53,4 +53,4 @@ The Slack alert destination is a configurable destination that allows alerts to ### Cooldown **NOTE: This is currently unimplemented** -To ensure that alerts aren't spammed to destinations once invoked, a time based cooldown value should exist that specifies how long an invariantSession must wait before it can propagate a trigged alert again. This value should be configurable by the user via a JSON-RPC request. \ No newline at end of file +To ensure that alerts aren't spammed to destinations once invoked, a time based cooldown value should exist that specifies how long an heuristicSession must wait before it can propagate a trigged alert again. This value should be configurable by the user via a JSON-RPC request. \ No newline at end of file diff --git a/docs/architecture/architecture.markdown b/docs/architecture/architecture.markdown index 8ea06270..41326164 100644 --- a/docs/architecture/architecture.markdown +++ b/docs/architecture/architecture.markdown @@ -6,16 +6,16 @@ permalink: /architecture ## Overview There are *three subsystems* that drive Pessimism’s architecture: -1. [ETL](etl.markdown) - Modularized data extraction system for retrieving and processing external chain data in the form of a DAG known as the Pipeline DAG -2. [Risk Engine](engine.markdown) - Logical execution platform that runs a set of invariants on the data funneled from the Pipeline DAG -3. [Alerting](alerting.markdown) - Alerting system that is used to notify users of invariant failures +1. [ETL](./etl.md) - Modularized data extraction system for retrieving and processing external chain data in the form of a DAG known as the Pipeline DAG +2. [Risk Engine](./engine.md) - Logical execution platform that runs a set of heuristics on the data funneled from the Pipeline DAG +3. [Alerting](./alerting.md) - Alerting system that is used to notify users of heuristic failures These systems will be accessible by a client through the use of a JSON-RPC API that has unilateral access to all three primary subsystems. The API will be supported to allow Pessimism users via client to: -1. Start invariant sessions -2. Update existing invariant sessions -3. Remove invariant sessions +1. Start heuristic sessions +2. Update existing heuristic sessions +3. Remove heuristic sessions ## Diagram The following diagram illustrates the core interaction flow between the three primary subsystems, API, and external data sources: diff --git a/docs/architecture/engine.markdown b/docs/architecture/engine.markdown index 6685d361..0fcd9bc2 100644 --- a/docs/architecture/engine.markdown +++ b/docs/architecture/engine.markdown @@ -10,9 +10,9 @@ permalink: /architecture/risk-engine ## Overview -The Risk Engine is responsible for handling and executing active invariants. It is the primary downstream consumer of ETL output. The Risk Engine will receive data from the ETL and execute the invariants associated with the data. If an invalidation occurs, the Risk Engine will return an `InvalidationOutcome` to the `EngineManager`. The `EngineManager` will then create an `Alert` using the `InvalidationOutcome` and publish it to the Alerting system. +The Risk Engine is responsible for handling and executing active heuristics. It is the primary downstream consumer of ETL output. The Risk Engine will receive data from the ETL and execute the heuristics associated with the data. If an invalidation occurs, the Risk Engine will return an `InvalidationOutcome` to the `EngineManager`. The `EngineManager` will then create an `Alert` using the `InvalidationOutcome` and publish it to the Alerting system. -The Risk Engine will execute the invariants associated with some ingested input data and return an `InvalidationOutcome` to the `EngineManager`. The `EngineManager` will then create an `Alert` using the `InvalidationOutcome` and publish it to the Alerting system. +The Risk Engine will execute the heuristics associated with some ingested input data and return an `InvalidationOutcome` to the `EngineManager`. The `EngineManager` will then create an `Alert` using the `InvalidationOutcome` and publish it to the Alerting system. The following diagram further exemplifies this key interaction: @@ -30,7 +30,7 @@ graph LR; end subgraph AA["ETL Manager"] - Z["engineRelay"] --> |"invariant input"|C + Z["engineRelay"] --> |"heuristic input"|C end subgraph AAA["Alerting Manager"] @@ -40,13 +40,13 @@ graph LR; {% endraw %} ## Inter-Connectivity -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. +The ETL publishes `Heuristic 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 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. +## Heuristic Session +An heuristic session refers to the execution and representation of a single heuristic. An heuristic session is uniquely identified by a `SUUID` and is associated with a single `PUUID`. An heuristic session is created by the `EngineManager` when a user requests to run an active session. The `EngineManager` will create a new `HeuristicSession` and pass it to the `RiskEngine` to be executed. The `RiskEngine` will then execute the heuristic 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. +The SUUID is a unique identifier that is used to identify a specific heuristic session. The SUUID is generated by the `EngineManager` when a user requests to run a new heuristic session. The SUUID is used to uniquely identify a specific heuristic session. This allows the `EngineManager` to perform operations on a specific heuristic session such as removing it or updating it. A `SUUID` constitutes of both a unique `UUID` and a `PID`. @@ -54,22 +54,22 @@ A `SessionPID` is encoded using the following 3 byte array sequence: ``` 0 1 2 3 |-----------|-----------|-----------| - network pipeline invariant + network pipeline heuristic type type type ``` -## Invariant Input -The invariant input is a struct that contains the following fields: -* `PUUID` - The ID of the invariant that the input data is intended for +## Heuristic Input +The heuristic input is a struct that contains the following fields: +* `PUUID` - The ID of the heuristic that the input data is intended for * `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 occurred. If an invalidation has occurred, the invariant will return a `InvalidationOutcome` that contains relevant metadata necessary for the `EngineManager` to create an `Alert`. +## Heuristic +An heuristic is a logical execution module that defines some set of invalidation criteria. The heuristic is responsible for processing the input data and determining if an invalidation has occurred. If an invalidation has occurred, the heuristic 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: +### Hardcoded Base Heuristic +Every hardcoded heuristic must implement an `Heuristic` interface to be compatible for invalidation by the `Hardcoded` Risk Engine type. Currently the interface is as follows: ``` -type Invariant interface { +type Heuristic interface { Addressing() bool InputType() core.RegisterType Invalidate(core.TransitData) (*core.InvalOutcome, bool, error) @@ -79,37 +79,37 @@ type Invariant interface { ``` -### Invariant Input Type -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. +### Heuristic Input Type +The heuristic input type is a `RegisterType` that defines the type of data that the heuristic will receive as input. The heuristic input type is defined by the `InputType()` method of the `Heuristic` interface. The heuristic input type is used by the `RiskEngine` to determine if the input data is compatible with the heuristic. If the input data is not compatible with the heuristic, the `RiskEngine` will not execute the heuristic and will return an error. ### Addressing -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. +All heuristics have a boolean property `Addressing` which determines if the heuristic is addressable. To be addressable, an heuristic 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. +For example, a `balance_enforcement` heuristic session will be addressable because it only executes invalidation logic for the native ETH balance of a single address. -### Invariant States -State is used to represent the current state of an invariant. The state of an invariant is represented by a `InvariantState` type. The following states are supported: -- `Running` - The invariant is currently running and is being executed by the `RiskEngine` -- `Inactive` - The invariant is currently inactive and is not being executed by the `RiskEngine` -- `Paused` - The invariant is currently paused and is not being executed by the `RiskEngine` +### Heuristic States +State is used to represent the current state of an heuristic. The state of an heuristic is represented by a `HeuristicState` type. The following states are supported: +- `Running` - The heuristic is currently running and is being executed by the `RiskEngine` +- `Inactive` - The heuristic is currently inactive and is not being executed by the `RiskEngine` +- `Paused` - The heuristic is currently paused and is not being executed by the `RiskEngine` ### Execution Type -A risk engine has an associated execution type that defines how the risk engine will execute the invariant. There are two types of execution: -1. `Hardcoded` - The invariant invalidation logic is hardcoded directly into the risk engine registry using native Go code. These invariants can only be changed by modifying the application source code of the engine registry. -2. `Dynamic` - The invariant invalidation logic is dynamically loaded and executed by a risk engine. These invariants can be changed without modifying the application source code of the engine registry. +A risk engine has an associated execution type that defines how the risk engine will execute the heuristic. There are two types of execution: +1. `Hardcoded` - The heuristic invalidation logic is hardcoded directly into the risk engine registry using native Go code. These heuristics can only be changed by modifying the application source code of the engine registry. +2. `Dynamic` - The heuristic invalidation logic is dynamically loaded and executed by a risk engine. These heuristics can be changed without modifying the application source code of the engine registry. **As of now, this is not supported.** -## Hardcoded Invariant Types -As of now, there are two types of hardcoded invariants that a user can deploy active sessions for: -- `invocation` - Invariant that is triggered when a specific smart contract function is invoked **Not currently supported** -- `balance_enforcement` - Invariant that checks an address's balance changes and ensures that the balance does not exceed a certain threshold +## Hardcoded Heuristic Types +As of now, there are two types of hardcoded heuristics that a user can deploy active sessions for: +- `invocation` - Heuristic that is triggered when a specific smart contract function is invoked **Not currently supported** +- `balance_enforcement` - Heuristic 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 implementation. The implementation must adhere to the interface specified for the `BaseInvariant` type. +### How to add a new heuristic +1. Create a new file in the `internal/engine/registry` directory that stores the heuristic implementation. The implementation must adhere to the interface specified for the `BaseHeuristic` type. -3. Add a new entry to the `InvariantType` enum in `internal/core/constants.go` +3. Add a new entry to the `HeuristicType` enum in `internal/core/constants.go` 2. Add a new entry to the registry in `internal/engine/registry/registry.go` -## Dynamic Invariant Types +## Dynamic Heuristic 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 heuristics 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` heuristics, dynamic heuristics can be deployed and executed without modifying the source code of the Pessimism application. diff --git a/docs/architecture/etl.markdown b/docs/architecture/etl.markdown index e13b3382..383d82f7 100644 --- a/docs/architecture/etl.markdown +++ b/docs/architecture/etl.markdown @@ -9,7 +9,7 @@ permalink: /architecture/etl {% endraw %} -The Pessimism ETL is a generalized abstraction for a DAG-based component system that continuously transforms chain data into inputs for consumption by a Risk Engine in the form of intertwined data “pipelines”. This DAG based representation of ETL operations is done to ensure that the application can optimally scale to support many active invariants. This design allows for the reuse of modularized ETL components and de-duplication of conflicting pipelines under certain key logical circumstances. +The Pessimism ETL is a generalized abstraction for a DAG-based component system that continuously transforms chain data into inputs for consumption by a Risk Engine in the form of intertwined data “pipelines”. This DAG based representation of ETL operations is done to ensure that the application can optimally scale to support many active heuristics. This design allows for the reuse of modularized ETL components and de-duplication of conflicting pipelines under certain key logical circumstances. ## Component A component refers to a graph node within the ETL system. Every component performs some operation for transforming data from any data source into a consumable input for the Risk Engine to ingest. @@ -81,7 +81,7 @@ Once input data processing has been completed, the output data is then submitted * An `ActivityState` channel with a pipeline manager * Ingress handler that other components can write to * `TransformFunc` - A processing function that performs some data translation/transformation on respective inputs -* An `egressHandler` that stores dependencies to write to (i.e. Other pipeline components, invariant engine) +* An `egressHandler` that stores dependencies to write to (i.e. Other pipeline components, heuristic engine) * A specified output data type #### Example Use Case(s) @@ -111,7 +111,7 @@ graph LR; #### Attributes * A communication channel with the pipeline manager * Poller/subscription logic that performs real-time data reads on some third-party source -* An `egressHandler` that stores dependencies to write to (i.e. Other pipeline components, invariant engine) +* An `egressHandler` that stores dependencies to write to (i.e. Other pipeline components, heuristic engine) * A specified output data type * _(Optional)_ Interface with some storage (postgres, mongo, etc.) to persist lively extracted data @@ -125,7 +125,7 @@ graph LR; ### (TBD) Aggregator **NOTE - This component type is still in-development** -Aggregators are used to solve the problem where a pipe or an invariant input will require multiple sources of data to perform an execution sequence. Since aggregators are subscribing to more than one data stream with different output frequencies, they must employ a synchronization policy for collecting and propagating multi-data inputs within a highly asynchronous environment. +Aggregators are used to solve the problem where a pipe or an heuristic input will require multiple sources of data to perform an execution sequence. Since aggregators are subscribing to more than one data stream with different output frequencies, they must employ a synchronization policy for collecting and propagating multi-data inputs within a highly asynchronous environment. #### Attributes * Able to read heterogenous transit data from an arbitrary number of component ingresses @@ -137,9 +137,9 @@ _Only send output at the update of a single ingress stream_ Single Value Subscription refers to a synchronization policy where a bucketed multi-data tuple is submitted every time there’s an update to a single input data queue. -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)`. +For example we can have an heuristic 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 heuristic will run every time there's an update or a new block from `ChainA`: ``` { "A:latest_blocks": [xi] where cardinality = 1, @@ -207,7 +207,7 @@ A `GethBlock` register refers to a block output extracted from a go-ethereum nod ### 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 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. +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 heuristic that uses this register must also be addressable. ## Managed ETL @@ -241,7 +241,7 @@ graph TB; ### Pipeline -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. +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 heuristic 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 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. @@ -258,12 +258,12 @@ A live pipeline is a pipeline that is actively running and performing ETL operat **Backtest** -A backtest pipeline is a pipeline that is used to sequentially backtest some component sequence from some starting to ending block height. For example, a backtest pipeline could be used to backtest a _balance_enforcement_ invariant between L1 block heights `0` to `1000`. +A backtest pipeline is a pipeline that is used to sequentially backtest some component sequence from some starting to ending block height. For example, a backtest pipeline could be used to backtest a _balance_enforcement_ heuristic between L1 block heights `0` to `1000`. ### Pipeline UUID (PUUID) All pipelines have a PUUID that stores critical identification data. Pipeline UUIDs are used by higher order abstractions to: -* Route invariant inputs between the ETL and Risk Engine +* Route heuristic 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 overlapping components can be deduplicated when viable. diff --git a/docs/invariants.markdown b/docs/heuristics.markdown similarity index 60% rename from docs/invariants.markdown rename to docs/heuristics.markdown index 09fea111..a06fe42f 100644 --- a/docs/invariants.markdown +++ b/docs/heuristics.markdown @@ -1,13 +1,17 @@ --- layout: page -title: Invariants -permalink: /invariants +title: Heuristics +permalink: /heuristics --- +# Heuristics + + ## Balance Enforcement -The hardcoded `balance_enforcement` invariant checks the native ETH balance of some address every `n` milliseconds and alerts to slack if the account's balance is ever less than `lower` or greater than `upper` value. This invariant is useful for monitoring hot wallets and other accounts that should always have a balance above a certain threshold. +The hardcoded `balance_enforcement` heuristic checks the native ETH balance of some address every `n` milliseconds and alerts to slack if the account's balance is ever less than `lower` or greater than `upper` value. This heuristic is useful for monitoring hot wallets and other accounts that should always have a balance above a certain threshold. ### Parameters + | Name | Type | Description | | ---- | ---- | ----------- | | address | string | The address to check the balance of | @@ -16,7 +20,7 @@ The hardcoded `balance_enforcement` invariant checks the native ETH balance of s ### Example Deploy Request ``` -curl --location --request POST 'http://localhost:8080/v0/invariant' \ +curl --location --request POST 'http://localhost:8080/v0/heuristic' \ --header 'Content-Type: text/plain' \ --data-raw '{ "method": "run", @@ -26,7 +30,7 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ "type": "balance_enforcement", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "address": "0xfC0157aA4F5DB7177830ACddB3D5a9BB5BE9cc5e", "lower": 1, "upper": 2 @@ -36,20 +40,22 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ ``` ## Contract Event -The hardcoded `contract_event` invariant scans newly produced blocks for a specific contract event and alerts to slack if the event is found. This invariant is useful for monitoring for specific contract events that should never occur. +The hardcoded `contract_event` heuristic scans newly produced blocks for a specific contract event and alerts to slack if the event is found. This heuristic is useful for monitoring for specific contract events that should never occur. ### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| address | string | The address of the contract to scan for the events | -| args | []string | The event signatures to scan for | -**NOTE:** The `args` field is an array of string event declarations (eg. `Transfer(address,address,uint256)`). Currently Pessimism makes no use of contract ABIs so the manually specified event declarations are not validated for correctness. If the event declaration is incorrect, the invariant session will never alert but will continue to scan. +| Name | Type | Description | +|---------|----------|----------------------------------------------------| +| address | string | The address of the contract to scan for the events | +| args | []string | The event signatures to scan for | + + +**NOTE:** The `args` field is an array of string event declarations (eg. `Transfer(address,address,uint256)`). Currently Pessimism makes no use of contract ABIs so the manually specified event declarations are not validated for correctness. If the event declaration is incorrect, the heuristic session will never alert but will continue to scan. ### Example Deploy Request ``` -curl --location --request POST 'http://localhost:8080/v0/invariant' \ +curl --location --request POST 'http://localhost:8080/v0/heuristic' \ --header 'Content-Type: text/plain' \ --data-raw '{ "method": "run", @@ -59,7 +65,7 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ "type": "contract_event", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "args": ["Transfer(address,address,uint256)"] } @@ -68,20 +74,21 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ ``` ## Withdrawal Enforcement -**NOTE:** This invariant requires an active RPC connection to both L1 and L2 networks. +**NOTE:** This heuristic requires an active RPC connection to both L1 and L2 networks. -The hardcoded `withdrawal_enforcement` invariant scans for active `WithdrawalProven` events on an L1Portal contract. Once an event is detected, the invariant proceeds to scan for the corresponding `withdrawlHash` event on the L2ToL1MesagePasser contract's internal state. If the `withdrawlHash` is not found, the invariant alerts to slack. +The hardcoded `withdrawal_enforcement` heuristic scans for active `WithdrawalProven` events on an L1Portal contract. Once an event is detected, the heuristic proceeds to scan for the corresponding `withdrawlHash` event on the L2ToL1MesagePasser contract's internal state. If the `withdrawlHash` is not found, the heuristic alerts to slack. ### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| l1_portal_address | string | The address of the L1Portal contract | -| l2_to_l1_address | string | The address of the L2ToL1MessagePasser contract | + +| Name | Type | Description | +|-------------------|--------|-------------------------------------------------| +| l1_portal_address | string | The address of the L1Portal contract | +| l2_to_l1_address | string | The address of the L2ToL1MessagePasser contract | ### Example Deploy Request ``` -curl --location --request POST 'http://localhost:8080/v0/invariant' \ +curl --location --request POST 'http://localhost:8080/v0/heuristic' \ --header 'Content-Type: text/plain' \ --data-raw '{ "method": "run", @@ -91,7 +98,7 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ "type": "withdrawal_enforcement", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "l1_portal_address": "0x111", "l2_to_l1_address": "0x333", }, @@ -99,21 +106,22 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ ``` ## Fault Detection -**NOTE:** This invariant requires an active RPC connection to both L1 and L2 networks. Furthermore, the Pessimism implementation of fault-detector assumes that a submitted L2 output on L1 will correspond to a canonical block on L2. +**NOTE:** This heuristic requires an active RPC connection to both L1 and L2 networks. Furthermore, the Pessimism implementation of fault-detector assumes that a submitted L2 output on L1 will correspond to a canonical block on L2. -The hardcoded `fault_detector` invariant scans for active `OutputProposed` events on an L1 Output Oracle contract. Once an event is detected, the invariant implementation proceeds to reconstruct a local state output for the corresponding L2 block. If there is a mismatch between the L1 output and the local state output, the invariant alerts. +The hardcoded `fault_detector` heuristic scans for active `OutputProposed` events on an L1 Output Oracle contract. Once an event is detected, the heuristic implementation proceeds to reconstruct a local state output for the corresponding L2 block. If there is a mismatch between the L1 output and the local state output, the heuristic alerts. ### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| l2_output_address | string | The address of the L1 output oracle | -| l2_to_l1_address | string | The address of the L2ToL1MessagePasser contract | + +| Name | Type | Description | +|-------------------|--------|-------------------------------------------------| +| l2_output_address | string | The address of the L1 output oracle | +| l2_to_l1_address | string | The address of the L2ToL1MessagePasser contract | ### Example Deploy Request ``` -curl --location --request POST 'http://localhost:8080/v0/invariant' \ +curl --location --request POST 'http://localhost:8080/v0/heuristic' \ --header 'Content-Type: text/plain' \ --data-raw '{ "method": "run", @@ -123,7 +131,7 @@ curl --location --request POST 'http://localhost:8080/v0/invariant' \ "type": "fault_detector", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "l2_output_address": "0x111", "l2_to_l1_address": "0x333", }, diff --git a/docs/index.markdown b/docs/index.markdown index d7b0a620..ad979f5a 100644 --- a/docs/index.markdown +++ b/docs/index.markdown @@ -6,12 +6,12 @@ Detect real-time threats on Op-stack compatible chains ## Contents - [Architecture](../pessimism/architecture) - - [JSON-RPC API](../pessimism/api) + - [REST API](../pessimism/api) - [ETL Subsystem](../pessimism/architecture/etl) - [Engine Subsystem](../pessimism/architecture/risk-engine) - [Alerting Subsystem](../pessimism/architecture/alerting) - [API Swaggerdoc](swaggerdoc.html) -- [Invariant Documentation](../pessimism/invariants) +- [Heuristic Documentation](../pessimism/heuristics) - [Telemetry Documentation](../pessimism/telemetry) ## Github Pages diff --git a/docs/openapi/swagger.yml b/docs/openapi/swagger.yml index a9c5504b..669ba87d 100644 --- a/docs/openapi/swagger.yml +++ b/docs/openapi/swagger.yml @@ -11,10 +11,10 @@ info: version: 0.0.1 externalDocs: description: Find out more about Pessimism's architecture - url: 'https://github.com/base-org/pessimism/blob/master/docs/ARCHITECTURE.md' + url: 'https://github.com/base-org/pessimism/blob/master/docs/architecture.md' tags: - - name: invariant - description: 'Invariant endpoints' + - name: heuristic + description: 'Heuristic endpoints' - name: system description: 'System operations' @@ -34,17 +34,17 @@ paths: schema: $ref: '#/components/schemas/HealthResponse' - /v0/invariant: + /v0/heuristic: get: tags: - - invariant - summary: Returns an invariant session. + - heuristic + summary: Returns an heuristic session. description: >- - Returns invariant session metadata for some specified session uuid. If no uuid is specified, then all sessions are returned. **NOTE - This is currently unimplemented.** + Returns heuristic session metadata for some specified session uuid. If no uuid is specified, then all sessions are returned. **NOTE - This is currently unimplemented.** parameters: - name: uuid in: query - description: 'Invariant session uuid' + description: 'Heuristic session uuid' required: false schema: type: string @@ -81,41 +81,41 @@ paths: post: tags: - - invariant - summary: Performs some invariant based system option (ie. starting invariant session, removing session and deleting session) + - heuristic + summary: Performs some heuristic based system option (ie. starting heuristic session, removing session and deleting session) description: >- - Returns operation status. Currently only supports running a new invariant session. Updating and deleting are still + Returns operation status. Currently only supports running a new heuristic session. Updating and deleting are still unimplemented. requestBody: - description: Invariant input + description: Heuristic input required: true content: application/json: schema: - $ref: '#/components/schemas/InvOperationParameters' + $ref: '#/components/schemas/HeuristicOperationParameters' examples: run: - $ref: '#/components/examples/run-inv-example' + $ref: '#/components/examples/run-heuristic-example' update: - $ref: '#/components/examples/update-inv-example' + $ref: '#/components/examples/update-heuristic-example' delete: - $ref: '#/components/examples/delete-inv-example' + $ref: '#/components/examples/delete-heuristic-example' responses: '200': description: 'Successful operation.' content: application/json: schema: - $ref: '#/components/schemas/InvariantResponse' + $ref: '#/components/schemas/HeuristicResponse' examples: default: - $ref: '#/components/examples/get-inv-result-success' + $ref: '#/components/examples/get-heuristic-response-success' '400': description: 'Unsuccessful request unmarshaling or validation.' content: application/json: schema: - $ref: '#/components/schemas/InvariantResponse' + $ref: '#/components/schemas/HeuristicResponse' examples: default: $ref: '#/components/examples/get-session-dne' @@ -124,38 +124,38 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/InvariantResponse' + $ref: '#/components/schemas/HeuristicResponse' examples: default: - $ref: '#/components/examples/get-inv-result-failed-unmarshal' + $ref: '#/components/examples/get-heuristic-result-failed-unmarshal' components: examples: - update-inv-example: + update-heuristic-example: value: method: update params: uuid: 0x420 - invariant_params: + heuristic_params: address: 0x420 upperBound: 666 lowerBound: 222 - delete-inv-example: + delete-heuristic-example: value: method: delete params: uuid: 0x420 - run-inv-example: + run-heuristic-example: value: method: run params: network: layer1 type: live - invariant: balance_enforcement + heuristic: balance_enforcement alert_destination: slack - invariant_params: + heuristic_params: address: 0x420 upperBound: 100 lowerBound: 0 @@ -177,9 +177,9 @@ components: uuid: 0x420 network: layer1 type: live - invariant: balance_enforcement + heuristic: balance_enforcement alert_destination: slack - invariant_params: + heuristic_params: address: 0x420 upperBound: 100 lowerBound: 0 @@ -190,21 +190,21 @@ components: deleted: false get-all-sessions-success: - value: {"status": "OK", "result": [{"uuid": "0x420", "network": "layer1", "type": "live", "invariant": "balance_enforcement", "alert_destination": "slack", "invariant_params": {"address": "0x420", "upperBound": 100, "lowerBound": 0}, "status": "running", "created_at": "2021-09-01T00:00:00Z", "updated_at": "2021-09-01T00:00:00Z", "deleted_at": "2021-09-01T00:00:00Z", "deleted": false}]} + value: {"status": "OK", "result": [{"uuid": "0x420", "network": "layer1", "type": "live", "heuristic": "balance_enforcement", "alert_destination": "slack", "heuristic_params": {"address": "0x420", "upperBound": 100, "lowerBound": 0}, "status": "running", "created_at": "2021-09-01T00:00:00Z", "updated_at": "2021-09-01T00:00:00Z", "deleted_at": "2021-09-01T00:00:00Z", "deleted": false}]} - get-inv-result-success: + get-heuristic-response-success: value: data: status: OK - result: {'invariant_uuid': 0x420} + result: {'heuristic_uuid': 0x420} - get-inv-result-failed-unmarshal: + get-heuristic-result-failed-unmarshal: value: data: status: NOTOK - result: {'error': 'failed to decode invariant request'} + result: {'error': 'failed to decode heuristic request'} - get-inv-result-internal-error: + get-heuristic-result-internal-error: value: data: status: NOTOK @@ -237,10 +237,10 @@ components: - live - backtest - InvariantTypeEnum: + HeuristicTypeEnum: type: string description: >- - The invariant type (balance_enforcement). + The heuristic type (balance_enforcement). enum: - balance_enforcement @@ -260,40 +260,40 @@ components: - Timestamp - Healthy - ### /v0/invariant POST - InvariantResponse: - description: Standardized response object for invariant operations. + ### /v0/heuristic POST + HeuristicResponse: + description: Standardized response object for heuristic operations. properties: status: type: string description: 'Response processing result' enum: [OK, NOTOK] result: - $ref: '#/components/schemas/InvOperationResult' + $ref: '#/components/schemas/HeuristicOpResult' - OkInvOperationResult: + OkHeuristicOpResult: type: object description: 'Response result object for successful requests' properties: uuid: type: string - NotOkInvOperationResult: + NotOkHeuristicOpResult: description: 'Response result object for failed requests' type: object properties: error: type: string - InvOperationResult: + HeuristicOpResult: type: object description: 'Response result object' oneOf: - - $ref: '#/components/schemas/OkInvOperationResult' - - $ref: '#/components/schemas/NotOkInvOperationResult' + - $ref: '#/components/schemas/OkHeuristicOpResult' + - $ref: '#/components/schemas/NotOkHeuristicOpResult' - BalanceInvConfig: + BalanceEnforceCfg: type: object - description: 'Balance invariant configuration parameters' + description: 'Balance heuristic configuration parameters' properties: address: description: 'Address to monitor' @@ -309,31 +309,31 @@ components: - upperBound - lowerBound - InvConfig: + HeuristicCfg: type: object - description: 'Invariant configuration parameters' + description: 'Heuristic configuration parameters' oneOf: - - $ref: '#/components/schemas/BalanceInvConfig' + - $ref: '#/components/schemas/BalanceEnforceCfg' - InvOperationParameters: - description: Standardized request object for performing invariant operations. + HeuristicOperationParameters: + description: Standardized request object for performing heuristic operations. properties: method: type: string enum: ['run', 'update', 'delete'] - description: Invariant method operation that's being invoked. + description: Heuristic method operation that's being invoked. params: - description: Invariant method parameters. + description: Heuristic method parameters. oneOf: - - $ref: '#/components/schemas/RunInvParameters' - - $ref: '#/components/schemas/UpdateInvParameters' - - $ref: '#/components/schemas/DeleteInvParameters' + - $ref: '#/components/schemas/RunHeuristicParams' + - $ref: '#/components/schemas/UpdateHeuristicParams' + - $ref: '#/components/schemas/DeleteHeuristicParams' required: - method - params ### method parameter object types - RunInvParameters: # RUN + RunHeuristicParams: # RUN type: object description: Parameters necessary to run a new session. properties: @@ -341,55 +341,55 @@ components: $ref: '#/components/schemas/NetworkEnum' type: $ref: '#/components/schemas/SessionTypeEnum' - invariant: - $ref: '#/components/schemas/InvariantTypeEnum' + heuristic: + $ref: '#/components/schemas/HeuristicTypeEnum' alert_destination: $ref: '#/components/schemas/AlertDestEnum' - invariant_params: - $ref: '#/components/schemas/InvConfig' + heuristic_params: + $ref: '#/components/schemas/HeuristicCfg' - UpdateInvParameters: #UPDATE + UpdateHeuristicParams: #UPDATE type: object description: Parameters necessary to update an existing session. properties: uuid: - description: 'Invariant session uuid' + description: 'Heuristic session uuid' type: string - invariant_params: - description: 'Invariant configuration parameters' - $ref: '#/components/schemas/InvConfig' + heuristic_params: + description: 'Heuristic configuration parameters' + $ref: '#/components/schemas/HeuristicCfg' required: - uuid - - invariant_params + - heuristic_params - DeleteInvParameters: #DELETE + DeleteHeuristicParams: #DELETE type: object description: Parameters necessary to update an existing session. properties: uuid: - description: 'Invariant session uuid' + description: 'Heuristic session uuid' type: string required: - uuid - ### /v0/invariant GET + ### /v0/heuristic GET SessionGetResponse: type: object - description: Metadata for some specified invariant session. + description: Metadata for some specified heuristic session. properties: uuid: type: string - description: 'Invariant session uuid' + description: 'Heuristic session uuid' network: $ref: '#/components/schemas/NetworkEnum' type: $ref: '#/components/schemas/SessionTypeEnum' - invariant: - $ref: '#/components/schemas/InvariantTypeEnum' + heuristic: + $ref: '#/components/schemas/HeuristicTypeEnum' alert_destination: $ref: '#/components/schemas/AlertDestEnum' - invariant_params: - $ref: '#/components/schemas/InvConfig' + heuristic_params: + $ref: '#/components/schemas/HeuristicCfg' status: type: string description: 'Session status' diff --git a/docs/telemetry.markdown b/docs/telemetry.markdown index 7a4ef1be..f86452fa 100644 --- a/docs/telemetry.markdown +++ b/docs/telemetry.markdown @@ -21,12 +21,12 @@ which can be pasted directly below to keep current system metric documentation u | METRIC | DESCRIPTION | LABELS | TYPE | |-------------------------------------------|--------------------------------------------------------|----------------------------------------|---------| | pessimism_up | 1 if the service is up | | gauge | -| pessimism_invariants_active_invariants | Number of active invariants | invariant,network,pipeline | gauge | +| pessimism_heuristics_active_heuristics | Number of active heuristics | heuristic,network,pipeline | gauge | | pessimism_etl_active_pipelines | Number of active pipelines | pipeline,network | gauge | -| pessimism_invariants_invariant_runs_total | Number of times a specific invariant has been run | network,invariant | counter | -| pessimism_alerts_generated_total | Number of total alerts generated for a given invariant | network,invariant,pipeline,destination | counter | +| pessimism_heuristics_heuristic_runs_total | Number of times a specific heuristic has been run | network,heuristic | counter | +| pessimism_alerts_generated_total | Number of total alerts generated for a given heuristic | network,heuristic,pipeline,destination | counter | | pessimism_node_errors_total | Number of node errors caught | node | counter | | pessimism_block_latency | Millisecond latency of block processing | network | gauge | | pessimism_pipeline_latency | Millisecond latency of pipeline processing | puuid | gauge | -| pessimism_invariant_execution_time | Nanosecond time of invariant execution | invariant | gauge | -| pessimism_invariant_errors_total | Number of errors generated by invariant executions | invariant | counter | +| pessimism_heuristic_execution_time | Nanosecond time of heuristic execution | heuristic | gauge | +| pessimism_heuristic_errors_total | Number of errors generated by heuristic executions | heuristic | counter | diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 0528c507..b290b687 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -30,7 +30,7 @@ import ( ) // Test_Balance_Enforcement ... Tests the E2E flow of a single -// balance enforcement invariant session on L2 network. +// balance enforcement heuristic session on L2 network. func Test_Balance_Enforcement(t *testing.T) { ts := e2e.CreateL2TestSuite(t) @@ -39,21 +39,21 @@ func Test_Balance_Enforcement(t *testing.T) { alice := ts.L2Cfg.Secrets.Addresses().Alice bob := ts.L2Cfg.Secrets.Addresses().Bob - // Deploy a balance enforcement invariant session for Alice. - err := ts.App.BootStrap([]*models.InvRequestParams{{ - Network: core.Layer2.String(), - PType: core.Live.String(), - InvType: core.BalanceEnforcement.String(), - StartHeight: nil, - EndHeight: nil, - AlertingDest: core.Slack.String(), + // Deploy a balance enforcement heuristic session for Alice. + err := ts.App.BootStrap([]*models.SessionRequestParams{{ + Network: core.Layer2.String(), + PType: core.Live.String(), + HeuristicType: core.BalanceEnforcement.String(), + StartHeight: nil, + EndHeight: nil, + AlertingDest: core.Slack.String(), SessionParams: map[string]interface{}{ "address": alice.String(), "lower": 3, // i.e. alert if balance is less than 3 ETH }, }}) - assert.NoError(t, err, "Failed to bootstrap balance enforcement invariant session") + assert.NoError(t, err, "Failed to bootstrap balance enforcement heuristic session") // Get Alice's balance. aliceAmt, err := ts.L2Geth.L2Client.BalanceAt(context.Background(), alice, nil) @@ -130,7 +130,7 @@ func Test_Balance_Enforcement(t *testing.T) { } // Test_Contract_Event ... Tests the E2E flow of a single -// contract event invariant session on L1 network. +// contract event heuristic session on L1 network. func Test_Contract_Event(t *testing.T) { ts := e2e.CreateSysTestSuite(t) @@ -141,20 +141,20 @@ func Test_Contract_Event(t *testing.T) { // The string declaration of the event we want to listen for. updateSig := "ConfigUpdate(uint256,uint8,bytes)" - // Deploy a contract event invariant session for the L1 system config address. - err := ts.App.BootStrap([]*models.InvRequestParams{{ - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.ContractEvent.String(), - StartHeight: nil, - EndHeight: nil, - AlertingDest: core.Slack.String(), + // Deploy a contract event heuristic session for the L1 system config address. + err := ts.App.BootStrap([]*models.SessionRequestParams{{ + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.ContractEvent.String(), + StartHeight: nil, + EndHeight: nil, + AlertingDest: core.Slack.String(), SessionParams: map[string]interface{}{ "address": predeploys.DevSystemConfigAddr.String(), "args": []interface{}{updateSig}, }, }}) - assert.NoError(t, err, "Error bootstrapping invariant session") + assert.NoError(t, err, "Error bootstrapping heuristic session") // Get bindings for the L1 system config contract. sysCfg, err := bindings.NewSystemConfig(predeploys.DevSystemConfigAddr, l1Client) @@ -196,8 +196,8 @@ type TestAccount struct { } // Test_Withdrawal_Enforcement ... Tests the E2E flow of a withdrawal -// / enforce invariant session. This test uses two L2ToL1 message passer contracts; -// one that is configured to be "faulty" and one that is not. The invariant session +// / enforce heuristic session. This test uses two L2ToL1 message passer contracts; +// one that is configured to be "faulty" and one that is not. The heuristic session // should only produce an alert when the faulty L2ToL1 message passer is used given // that it's state is empty. func Test_Withdrawal_Enforcement(t *testing.T) { @@ -246,37 +246,37 @@ func Test_Withdrawal_Enforcement(t *testing.T) { fromAddr := crypto.PubkeyToAddress(transactor.Key.PublicKey) // Setup Pessimism to listen for fraudulent withdrawals - // We use two invariants here; one configured with a dummy L1 message passer + // We use two heuristics here; one configured with a dummy L1 message passer // and one configured with the real L2->L1 message passer contract. This allows us to // ensure that an alert is only produced using faulty message passer. - err = ts.App.BootStrap([]*models.InvRequestParams{ + err = ts.App.BootStrap([]*models.SessionRequestParams{ { // This is the one that should produce an alert - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.WithdrawalEnforcement.String(), - StartHeight: nil, - EndHeight: nil, - AlertingDest: core.Slack.String(), + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.WithdrawalEnforcement.String(), + StartHeight: nil, + EndHeight: nil, + AlertingDest: core.Slack.String(), SessionParams: map[string]interface{}{ core.L1Portal: predeploys.DevOptimismPortal, core.L2ToL1MessagePasser: fakeAddr.String(), }, }, { - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.WithdrawalEnforcement.String(), - StartHeight: nil, - EndHeight: nil, - AlertingDest: core.Slack.String(), + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.WithdrawalEnforcement.String(), + StartHeight: nil, + EndHeight: nil, + AlertingDest: core.Slack.String(), SessionParams: map[string]interface{}{ core.L1Portal: predeploys.DevOptimismPortal, core.L2ToL1MessagePasser: predeploys.L2ToL1MessagePasserAddr.String(), }, }, }) - assert.NoError(t, err, "Error bootstrapping invariant session") + assert.NoError(t, err, "Error bootstrapping heuristic session") // Initiate Withdrawal. withdrawAmount := big.NewInt(500_000_000_000) @@ -376,14 +376,14 @@ func Test_Fault_Detector(t *testing.T) { reader, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client) assert.Nil(t, err) - // Deploys a fault detector invariant session instance using the locally spun-up Op-Stack chain - err = ts.App.BootStrap([]*models.InvRequestParams{{ - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.FaultDetector.String(), - StartHeight: big.NewInt(0), - EndHeight: nil, - AlertingDest: core.Slack.String(), + // Deploys a fault detector heuristic session instance using the locally spun-up Op-Stack chain + err = ts.App.BootStrap([]*models.SessionRequestParams{{ + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.FaultDetector.String(), + StartHeight: big.NewInt(0), + EndHeight: nil, + AlertingDest: core.Slack.String(), SessionParams: map[string]interface{}{ core.L2OutputOracle: predeploys.DevL2OutputOracle, core.L2ToL1MessagePasser: predeploys.L2ToL1MessagePasser, diff --git a/genesis.example.json b/genesis.example.json index b385bedd..0d605a8e 100644 --- a/genesis.example.json +++ b/genesis.example.json @@ -5,7 +5,7 @@ "type": "contract_event", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "address": "0xfC0157aA4F5DB7177830ACddB3D5a9BB5BE9cc5e", "args": ["Transfer(address, address, uint256)"] } @@ -16,7 +16,7 @@ "type": "balance_enforcement", "start_height": null, "alert_destination": "slack", - "invariant_params": { + "heuristic_params": { "address": "0xfC0157aA4F5DB7177830ACddB3D5a9BB5BE9cc5e", "lower": 1, "upper": 2 diff --git a/internal/alert/interpolator.go b/internal/alert/interpolator.go index 88c070c8..bee5c651 100644 --- a/internal/alert/interpolator.go +++ b/internal/alert/interpolator.go @@ -12,9 +12,9 @@ const ( // slackMsgFmt ... Slack message format SlackMsgFmt = ` - ⚠️🚨 Pessimism Alert: %s Invariant Invalidation 🚨⚠️ + ⚠️🚨 Pessimism Alert: %s 🚨⚠️ - _Invariant invalidation conditions met_ + _Heuristic activation conditions met_ _Network:_ %s _Session UUID:_ %s @@ -37,10 +37,10 @@ func NewInterpolator() Interpolator { return &interpolator{} } -// InterpolateSlackMessage ... Interpolates a slack message with the given invariant session UUID and message +// InterpolateSlackMessage ... Interpolates a slack message with the given heuristic session UUID and message func (*interpolator) InterpolateSlackMessage(sUUID core.SUUID, message string) string { return fmt.Sprintf(SlackMsgFmt, - sUUID.PID.InvType().String(), + sUUID.PID.HeuristicType().String(), sUUID.PID.Network(), sUUID.String(), fmt.Sprintf(CodeBlockFmt, message)) diff --git a/internal/alert/interpolator_test.go b/internal/alert/interpolator_test.go index 79da9428..c2c7dc56 100644 --- a/internal/alert/interpolator_test.go +++ b/internal/alert/interpolator_test.go @@ -13,7 +13,7 @@ func Test_InterpolateSlackMessage(t *testing.T) { msg := "Friedrich Nietzsche" - expected := "\n\t⚠️🚨 Pessimism Alert: unknown Invariant Invalidation 🚨⚠️\n\n\t_Invariant invalidation conditions met_\n\n\t_Network:_ unknown\n\t_Session UUID:_ unknown:unknown:unknown::000000000\n\n\t*Assessment Content:* \n\t```Friedrich Nietzsche```\t\n\t" + expected := "\n\t⚠️🚨 Pessimism Alert: unknown 🚨⚠️\n\n\t_Heuristic activation conditions met_\n\n\t_Network:_ unknown\n\t_Session UUID:_ unknown:unknown:unknown::000000000\n\n\t*Assessment Content:* \n\t```Friedrich Nietzsche```\t\n\t" actual := alert.NewInterpolator(). InterpolateSlackMessage(sUUID, msg) diff --git a/internal/alert/manager.go b/internal/alert/manager.go index d5a4c855..07e4086e 100644 --- a/internal/alert/manager.go +++ b/internal/alert/manager.go @@ -55,7 +55,7 @@ func NewManager(ctx context.Context, sc client.SlackClient) Manager { return am } -// AddSession ... Adds an invariant session to the alert manager store +// AddSession ... Adds an heuristic session to the alert manager store func (am *alertManager) AddSession(sUUID core.SUUID, alertDestination core.AlertDestination) error { return am.store.AddAlertDestination(sUUID, alertDestination) } diff --git a/internal/alert/store.go b/internal/alert/store.go index ab313e64..d8f9a26d 100644 --- a/internal/alert/store.go +++ b/internal/alert/store.go @@ -6,7 +6,7 @@ import ( "github.com/base-org/pessimism/internal/core" ) -// TODO(#81): No Support for Multiple Alerting Destinations for an Invariant Session +// TODO(#81): No Support for Multiple Alerting Destinations for an Heuristic Session // Store ... Interface for alert store // NOTE - This is a simple in-memory store, using this interface @@ -28,23 +28,23 @@ func NewStore() Store { } } -// AddAlertDestination ... Adds an alert destination for the given invariant session UUID -// NOTE - There can only be one alert destination per invariant session UUID +// AddAlertDestination ... Adds an alert destination for the given heuristic session UUID +// NOTE - There can only be one alert destination per heuristic session UUID func (am *store) AddAlertDestination(sUUID core.SUUID, alertDestination core.AlertDestination) error { if _, exists := am.alertMap[sUUID]; exists { - return fmt.Errorf("alert destination already exists for invariant session %s", sUUID.String()) + return fmt.Errorf("alert destination already exists for heuristic session %s", sUUID.String()) } am.alertMap[sUUID] = alertDestination return nil } -// GetAlertDestination ... Returns the alert destination for the given invariant session UUID +// GetAlertDestination ... Returns the alert destination for the given heuristic session UUID func (am *store) GetAlertDestination(sUUID core.SUUID) (core.AlertDestination, error) { dest, exists := am.alertMap[sUUID] if !exists { - return 0, fmt.Errorf("alert destination does not exist for invariant session %s", sUUID.String()) + return 0, fmt.Errorf("alert destination does not exist for heuristic session %s", sUUID.String()) } return dest, nil diff --git a/internal/api/handlers/handlers.go b/internal/api/handlers/handlers.go index 5bde3b39..43fec5f3 100644 --- a/internal/api/handlers/handlers.go +++ b/internal/api/handlers/handlers.go @@ -13,7 +13,7 @@ import ( type Handlers interface { HealthCheck(w http.ResponseWriter, r *http.Request) - RunInvariant(w http.ResponseWriter, r *http.Request) + RunHeuristic(w http.ResponseWriter, r *http.Request) ServeHTTP(w http.ResponseWriter, r *http.Request) } @@ -29,7 +29,7 @@ type Route = string const ( healthRoute = "/health" - invariantRoute = "/v0/invariant" + heuristicRoute = "/v0/heuristic" ) // New ... Initializer @@ -42,7 +42,7 @@ func New(ctx context.Context, service service.Service) (Handlers, error) { router.Use(pess_middleware.InjectedLogging(logging.NoContext())) registerEndpoint(healthRoute, router.Get, handlers.HealthCheck) - registerEndpoint(invariantRoute, router.Post, handlers.RunInvariant) + registerEndpoint(heuristicRoute, router.Post, handlers.RunHeuristic) handlers.router = router diff --git a/internal/api/handlers/heuristic.go b/internal/api/handlers/heuristic.go new file mode 100644 index 00000000..875aaf48 --- /dev/null +++ b/internal/api/handlers/heuristic.go @@ -0,0 +1,42 @@ +package handlers + +import ( + "encoding/json" + "net/http" + + "github.com/base-org/pessimism/internal/api/models" + "github.com/base-org/pessimism/internal/logging" + "github.com/go-chi/render" + "go.uber.org/zap" +) + +func renderHeuristicResponse(w http.ResponseWriter, r *http.Request, + ir *models.SessionResponse) { + w.WriteHeader(ir.Code) + render.JSON(w, r, ir) +} + +// RunHeuristic ... Handle heuristic run request +func (ph *PessimismHandler) RunHeuristic(w http.ResponseWriter, r *http.Request) { + var body *models.SessionRequestBody + + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + logging.WithContext(ph.ctx). + Error("Could not unmarshal request", zap.Error(err)) + + renderHeuristicResponse(w, r, + models.NewSessionUnmarshalErrResp()) + return + } + + sUUID, err := ph.service.ProcessHeuristicRequest(body) + if err != nil { + logging.WithContext(ph.ctx). + Error("Could not process heuristic request", zap.Error(err)) + + renderHeuristicResponse(w, r, models.NewSessionNoProcessResp()) + return + } + + renderHeuristicResponse(w, r, models.NewSessionAcceptedResp(sUUID)) +} diff --git a/internal/api/handlers/invariant_test.go b/internal/api/handlers/heuristic_test.go similarity index 74% rename from internal/api/handlers/invariant_test.go rename to internal/api/handlers/heuristic_test.go index ea2123e4..cde610b8 100644 --- a/internal/api/handlers/invariant_test.go +++ b/internal/api/handlers/heuristic_test.go @@ -16,7 +16,7 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_ProcessInvariantRequest(t *testing.T) { +func Test_ProcessHeuristicRequest(t *testing.T) { var tests = []struct { name string @@ -27,9 +27,9 @@ func Test_ProcessInvariantRequest(t *testing.T) { testLogic func(*testing.T, testSuite) }{ { - name: "Get Invariant Failure", + name: "Get Heuristic Failure", description: "When provided a malformed request body, a failed decoding response should be returned", - function: "RunInvariant", + function: "RunHeuristic", constructionLogic: func() testSuite { ts := createTestSuite(t) @@ -42,7 +42,7 @@ func Test_ProcessInvariantRequest(t *testing.T) { testBody := bytes.NewBuffer([]byte{0x42}) r := httptest.NewRequest(http.MethodGet, testAddress, testBody) - ts.testHandler.RunInvariant(w, r) + ts.testHandler.RunHeuristic(w, r) res := w.Result() data, err := io.ReadAll(res.Body) @@ -50,23 +50,23 @@ func Test_ProcessInvariantRequest(t *testing.T) { t.Errorf("Error: %v", err) } - actualResp := &models.InvResponse{} + actualResp := &models.SessionResponse{} err = json.Unmarshal(data, actualResp) assert.NoError(t, err) - assert.Equal(t, models.NewInvUnmarshalErrResp(), actualResp) + assert.Equal(t, models.NewSessionUnmarshalErrResp(), actualResp) }, }, { - name: "Process Invariant Failure", + name: "Process Heuristic Failure", description: "When provided an internal error occurs, a failed processing response should be returned", - function: "RunInvariant", + function: "RunHeuristic", constructionLogic: func() testSuite { ts := createTestSuite(t) ts.mockSvc.EXPECT(). - ProcessInvariantRequest(gomock.Any()). + ProcessHeuristicRequest(gomock.Any()). Return(core.NilSUUID(), testError1()). Times(1) @@ -76,12 +76,12 @@ func Test_ProcessInvariantRequest(t *testing.T) { testLogic: func(t *testing.T, ts testSuite) { w := httptest.NewRecorder() - testBody, _ := json.Marshal(models.InvRequestBody{Method: "run"}) + testBody, _ := json.Marshal(models.SessionRequestBody{Method: "run"}) testBytes := bytes.NewBuffer(testBody) r := httptest.NewRequest(http.MethodGet, testAddress, testBytes) - ts.testHandler.RunInvariant(w, r) + ts.testHandler.RunHeuristic(w, r) res := w.Result() data, err := io.ReadAll(res.Body) @@ -89,23 +89,23 @@ func Test_ProcessInvariantRequest(t *testing.T) { t.Errorf("Error: %v", err) } - actualResp := &models.InvResponse{} + actualResp := &models.SessionResponse{} err = json.Unmarshal(data, actualResp) assert.NoError(t, err) - assert.Equal(t, models.NewInvNoProcessInvResp(), actualResp) + assert.Equal(t, models.NewSessionNoProcessResp(), actualResp) }, }, { - name: "Process Invariant Success", - description: "When an invariant is successfully processed, a suuid should be rendered", - function: "RunInvariant", + name: "Process Heuristic Success", + description: "When an heuristic is successfully processed, a suuid should be rendered", + function: "RunHeuristic", constructionLogic: func() testSuite { ts := createTestSuite(t) ts.mockSvc.EXPECT(). - ProcessInvariantRequest(gomock.Any()). + ProcessHeuristicRequest(gomock.Any()). Return(testSUUID1(), nil). Times(1) @@ -115,12 +115,12 @@ func Test_ProcessInvariantRequest(t *testing.T) { testLogic: func(t *testing.T, ts testSuite) { w := httptest.NewRecorder() - testBody, _ := json.Marshal(models.InvRequestBody{Method: "run"}) + testBody, _ := json.Marshal(models.SessionRequestBody{Method: "run"}) testBytes := bytes.NewBuffer(testBody) r := httptest.NewRequest(http.MethodGet, testAddress, testBytes) - ts.testHandler.RunInvariant(w, r) + ts.testHandler.RunHeuristic(w, r) res := w.Result() data, err := io.ReadAll(res.Body) @@ -128,7 +128,7 @@ func Test_ProcessInvariantRequest(t *testing.T) { t.Errorf("Error: %v", err) } - actualResp := &models.InvResponse{} + actualResp := &models.SessionResponse{} err = json.Unmarshal(data, actualResp) assert.NoError(t, err) diff --git a/internal/api/handlers/invariant.go b/internal/api/handlers/invariant.go deleted file mode 100644 index 10100184..00000000 --- a/internal/api/handlers/invariant.go +++ /dev/null @@ -1,42 +0,0 @@ -package handlers - -import ( - "encoding/json" - "net/http" - - "github.com/base-org/pessimism/internal/api/models" - "github.com/base-org/pessimism/internal/logging" - "github.com/go-chi/render" - "go.uber.org/zap" -) - -func renderInvariantResponse(w http.ResponseWriter, r *http.Request, - ir *models.InvResponse) { - w.WriteHeader(ir.Code) - render.JSON(w, r, ir) -} - -// RunInvariant ... Handle invariant run request -func (ph *PessimismHandler) RunInvariant(w http.ResponseWriter, r *http.Request) { - var body *models.InvRequestBody - - if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - logging.WithContext(ph.ctx). - Error("Could not unmarshal request", zap.Error(err)) - - renderInvariantResponse(w, r, - models.NewInvUnmarshalErrResp()) - return - } - - sUUID, err := ph.service.ProcessInvariantRequest(body) - if err != nil { - logging.WithContext(ph.ctx). - Error("Could not process invariant request", zap.Error(err)) - - renderInvariantResponse(w, r, models.NewInvNoProcessInvResp()) - return - } - - renderInvariantResponse(w, r, models.NewInvAcceptedResp(sUUID)) -} diff --git a/internal/api/models/heuristic.go b/internal/api/models/heuristic.go new file mode 100644 index 00000000..7a6cbb84 --- /dev/null +++ b/internal/api/models/heuristic.go @@ -0,0 +1,141 @@ +package models + +import ( + "math/big" + "time" + + "github.com/base-org/pessimism/internal/core" +) + +// HeuristicMethod ... Represents the heuristic operation method +type HeuristicMethod int + +const ( + Run HeuristicMethod = iota + // NOTE - Update is not implemented yet + Update + // NOTE - Stop is not implemented yet + Stop +) + +func StringToHeuristicMethod(s string) HeuristicMethod { + switch s { + case "run": + return Run + case "update": + return Update + case "stop": + return Stop + default: + return Run + } +} + +// SessionResponseStatus ... Represents the heuristic operation response status +type SessionResponseStatus string + +const ( + OK SessionResponseStatus = "OK" + NotOK SessionResponseStatus = "NOTOK" +) + +// SessionRequestParams ... Request params for heuristic operation +type SessionRequestParams struct { + Network string `json:"network"` + PType string `json:"pipeline_type"` + HeuristicType string `json:"type"` + + StartHeight *big.Int `json:"start_height"` + EndHeight *big.Int `json:"end_height"` + + SessionParams map[string]interface{} `json:"heuristic_params"` + // TODO(#81): No Support for Multiple Alerting Destinations for an Heuristic Session + AlertingDest string `json:"alert_destination"` +} + +// Params ... Returns the heuristic session params +func (hrp *SessionRequestParams) Params() *core.SessionParams { + isp := core.NewSessionParams() + + for k, v := range hrp.SessionParams { + isp.SetValue(k, v) + } + + return isp +} + +// AlertingDestType ... Returns the alerting destination type +func (hrp *SessionRequestParams) AlertingDestType() core.AlertDestination { + return core.StringToAlertingDestType(hrp.AlertingDest) +} + +// NetworkType ... Returns the network type +func (hrp *SessionRequestParams) NetworkType() core.Network { + return core.StringToNetwork(hrp.Network) +} + +// PipelineType ... Returns the pipeline type +func (hrp *SessionRequestParams) PipelineType() core.PipelineType { + return core.StringToPipelineType(hrp.PType) +} + +// Heuristic ... Returns the heuristic type +func (hrp *SessionRequestParams) Heuristic() core.HeuristicType { + return core.StringToHeuristicType(hrp.HeuristicType) +} + +// GeneratePipelineConfig ... Generates a pipeline config using the request params +func (hrp *SessionRequestParams) GeneratePipelineConfig(pollInterval time.Duration, + regType core.RegisterType) *core.PipelineConfig { + return &core.PipelineConfig{ + Network: hrp.NetworkType(), + DataType: regType, + PipelineType: hrp.PipelineType(), + ClientConfig: &core.ClientConfig{ + Network: hrp.NetworkType(), + PollInterval: pollInterval, + StartHeight: hrp.StartHeight, + EndHeight: hrp.EndHeight, + }, + } +} + +// SessionConfig ... Generates a session config using the request params +func (hrp *SessionRequestParams) SessionConfig() *core.SessionConfig { + return &core.SessionConfig{ + AlertDest: hrp.AlertingDestType(), + Type: hrp.Heuristic(), + Params: hrp.Params(), + PT: hrp.PipelineType(), + } +} + +// SessionRequestBody ... Request body for heuristic operation request +type SessionRequestBody struct { + Method string `json:"method"` + Params SessionRequestParams `json:"params"` +} + +func (irb *SessionRequestBody) Clone() *SessionRequestBody { + return &SessionRequestBody{ + Method: irb.Method, + Params: irb.Params, + } +} + +// MethodType ... Returns the heuristic method type +func (irb *SessionRequestBody) MethodType() HeuristicMethod { + return StringToHeuristicMethod(irb.Method) +} + +// Result ... Result of heuristic operation +type Result = map[string]string + +// SessionResponse ... Response for heuristic operation request +type SessionResponse struct { + Code int `json:"status_code"` + Status SessionResponseStatus `json:"status"` + + Result Result `json:"result"` + Error string `json:"error"` +} diff --git a/internal/api/models/invariant_test.go b/internal/api/models/heuristic_test.go similarity index 66% rename from internal/api/models/invariant_test.go rename to internal/api/models/heuristic_test.go index 910ca0fe..f56fa184 100644 --- a/internal/api/models/invariant_test.go +++ b/internal/api/models/heuristic_test.go @@ -8,19 +8,19 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_InvRequestParams(t *testing.T) { +func Test_SessionRequestParams(t *testing.T) { - // Use a single instance of InvRequestParams for tests - irp := &models.InvRequestParams{ + // Use a single instance of SessionRequestParams for tests + irp := &models.SessionRequestParams{ SessionParams: map[string]interface{}{ "test": "test", }, - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.BalanceEnforcement.String(), + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.BalanceEnforcement.String(), } - // Ensure that the invariant request params are set correctly + // Ensure that the heuristic request params are set correctly params := irp.Params() v, err := params.Value("test") assert.NoError(t, err) @@ -34,8 +34,8 @@ func Test_InvRequestParams(t *testing.T) { pt := irp.PipelineType() assert.Equal(t, pt, core.Live) - // Ensure that invariant type is set correctly - it := irp.InvariantType() + // Ensure that heuristic type is set correctly + it := irp.Heuristic() assert.Equal(t, it, core.BalanceEnforcement) // Ensure that the pipeline config is set correctly @@ -49,10 +49,10 @@ func Test_InvRequestParams(t *testing.T) { assert.Equal(t, sConfig.Params, params) } -func Test_InvariantRequestBody(t *testing.T) { - irb := &models.InvRequestBody{ +func Test_HeuristicRequestBody(t *testing.T) { + irb := &models.SessionRequestBody{ Method: "test", - Params: models.InvRequestParams{}, + Params: models.SessionRequestParams{}, } // Ensure clone works @@ -61,5 +61,5 @@ func Test_InvariantRequestBody(t *testing.T) { assert.Equal(t, clone.Params, irb.Params) // Ensure that method type works - assert.Equal(t, irb.MethodType(), models.InvariantMethod(0)) + assert.Equal(t, irb.MethodType(), models.HeuristicMethod(0)) } diff --git a/internal/api/models/invariant.go b/internal/api/models/invariant.go deleted file mode 100644 index 8f9b9882..00000000 --- a/internal/api/models/invariant.go +++ /dev/null @@ -1,141 +0,0 @@ -package models - -import ( - "math/big" - "time" - - "github.com/base-org/pessimism/internal/core" -) - -// InvariantMethod ... Represents the invariant operation method -type InvariantMethod int - -const ( - Run InvariantMethod = iota - // NOTE - Update is not implemented yet - Update - // NOTE - Stop is not implemented yet - Stop -) - -func StringToInvariantMethod(s string) InvariantMethod { - switch s { - case "run": - return Run - case "update": - return Update - case "stop": - return Stop - default: - return Run - } -} - -// InvResponseStatus ... Represents the invariant operation response status -type InvResponseStatus string - -const ( - OK InvResponseStatus = "OK" - NotOK InvResponseStatus = "NOTOK" -) - -// InvRequestParams ... Request params for invariant operation -type InvRequestParams struct { - Network string `json:"network"` - PType string `json:"pipeline_type"` - InvType string `json:"type"` - - StartHeight *big.Int `json:"start_height"` - EndHeight *big.Int `json:"end_height"` - - SessionParams map[string]interface{} `json:"invariant_params"` - // TODO(#81): No Support for Multiple Alerting Destinations for an Invariant Session - AlertingDest string `json:"alert_destination"` -} - -// Params ... Returns the invariant session params -func (irp *InvRequestParams) Params() *core.InvSessionParams { - isp := core.NewSessionParams() - - for k, v := range irp.SessionParams { - isp.SetValue(k, v) - } - - return isp -} - -// AlertingDestType ... Returns the alerting destination type -func (irp *InvRequestParams) AlertingDestType() core.AlertDestination { - return core.StringToAlertingDestType(irp.AlertingDest) -} - -// NetworkType ... Returns the network type -func (irp *InvRequestParams) NetworkType() core.Network { - return core.StringToNetwork(irp.Network) -} - -// PipelineType ... Returns the pipeline type -func (irp *InvRequestParams) PipelineType() core.PipelineType { - return core.StringToPipelineType(irp.PType) -} - -// InvariantType ... Returns the invariant type -func (irp *InvRequestParams) InvariantType() core.InvariantType { - return core.StringToInvariantType(irp.InvType) -} - -// GeneratePipelineConfig ... Generates a pipeline config using the request params -func (irp *InvRequestParams) GeneratePipelineConfig(pollInterval time.Duration, - regType core.RegisterType) *core.PipelineConfig { - return &core.PipelineConfig{ - Network: irp.NetworkType(), - DataType: regType, - PipelineType: irp.PipelineType(), - ClientConfig: &core.ClientConfig{ - Network: irp.NetworkType(), - PollInterval: pollInterval, - StartHeight: irp.StartHeight, - EndHeight: irp.EndHeight, - }, - } -} - -// SessionConfig ... Generates a session config using the request params -func (irp *InvRequestParams) SessionConfig() *core.SessionConfig { - return &core.SessionConfig{ - AlertDest: irp.AlertingDestType(), - Type: irp.InvariantType(), - Params: irp.Params(), - PT: irp.PipelineType(), - } -} - -// InvRequestBody ... Request body for invariant operation request -type InvRequestBody struct { - Method string `json:"method"` - Params InvRequestParams `json:"params"` -} - -func (irb *InvRequestBody) Clone() *InvRequestBody { - return &InvRequestBody{ - Method: irb.Method, - Params: irb.Params, - } -} - -// MethodType ... Returns the invariant method type -func (irb *InvRequestBody) MethodType() InvariantMethod { - return StringToInvariantMethod(irb.Method) -} - -// InvResult ... Result of invariant operation -type InvResult = map[string]string - -// InvResponse ... Response for invariant operation request -type InvResponse struct { - Code int `json:"status_code"` - Status InvResponseStatus `json:"status"` - - Result InvResult `json:"result"` - Error string `json:"error"` -} diff --git a/internal/api/models/models.go b/internal/api/models/models.go index d2b9cbc5..dd600f99 100644 --- a/internal/api/models/models.go +++ b/internal/api/models/models.go @@ -7,29 +7,29 @@ import ( "github.com/base-org/pessimism/internal/logging" ) -// NewInvAcceptedResp ...Returns an invariant response with status accepted -func NewInvAcceptedResp(id core.SUUID) *InvResponse { - return &InvResponse{ +// NewSessionAcceptedResp ...Returns an heuristic response with status accepted +func NewSessionAcceptedResp(id core.SUUID) *SessionResponse { + return &SessionResponse{ Status: OK, Code: http.StatusAccepted, - Result: InvResult{logging.SUUIDKey: id.String()}, + Result: Result{logging.SUUIDKey: id.String()}, } } -// NewInvUnmarshalErrResp ... New unmarshal error response construction -func NewInvUnmarshalErrResp() *InvResponse { - return &InvResponse{ +// NewSessionUnmarshalErrResp ... New unmarshal error response construction +func NewSessionUnmarshalErrResp() *SessionResponse { + return &SessionResponse{ Status: NotOK, Code: http.StatusBadRequest, Error: "could not unmarshal request body", } } -// NewInvNoProcessInvResp ... New internal processing response error -func NewInvNoProcessInvResp() *InvResponse { - return &InvResponse{ +// NewSessionNoProcessResp ... New internal processing response error +func NewSessionNoProcessResp() *SessionResponse { + return &SessionResponse{ Status: NotOK, Code: http.StatusInternalServerError, - Error: "error processing invariant request", + Error: "error processing heuristic request", } } diff --git a/internal/api/service/health_test.go b/internal/api/service/health_test.go index 9114be8b..f041657b 100644 --- a/internal/api/service/health_test.go +++ b/internal/api/service/health_test.go @@ -22,7 +22,7 @@ func Test_GetHealth(t *testing.T) { { name: "Get Health Success", description: "", - function: "ProcessInvariantRequest", + function: "ProcessHeuristicRequest", constructionLogic: func() *testSuite { ts := createTestSuite(ctrl) @@ -47,7 +47,7 @@ func Test_GetHealth(t *testing.T) { { name: "Get Unhealthy Response", description: "Emulates unhealthy rpc endpoints", - function: "ProcessInvariantRequest", + function: "ProcessHeuristicRequest", constructionLogic: func() *testSuite { ts := createTestSuite(ctrl) diff --git a/internal/api/service/invariant.go b/internal/api/service/heuristic.go similarity index 52% rename from internal/api/service/invariant.go rename to internal/api/service/heuristic.go index 802ba799..c5573e60 100644 --- a/internal/api/service/invariant.go +++ b/internal/api/service/heuristic.go @@ -5,18 +5,18 @@ import ( "github.com/base-org/pessimism/internal/core" ) -// ProcessInvariantRequest ... Processes an invariant request type -func (svc *PessimismService) ProcessInvariantRequest(ir *models.InvRequestBody) (core.SUUID, error) { - if ir.MethodType() == models.Run { // Deploy invariant session - return svc.RunInvariantSession(&ir.Params) +// ProcessHeuristicRequest ... Processes an heuristic request type +func (svc *PessimismService) ProcessHeuristicRequest(ir *models.SessionRequestBody) (core.SUUID, error) { + if ir.MethodType() == models.Run { // Deploy heuristic session + return svc.RunHeuristicSession(&ir.Params) } // TODO - Add support for other method types (ie. delete. update) return core.NilSUUID(), nil } -// RunInvariantSession ... Runs an invariant session provided -func (svc *PessimismService) RunInvariantSession(params *models.InvRequestParams) (core.SUUID, error) { +// RunHeuristicSession ... Runs an heuristic session provided +func (svc *PessimismService) RunHeuristicSession(params *models.SessionRequestParams) (core.SUUID, error) { pConfig, err := svc.m.BuildPipelineCfg(params) if err != nil { return core.NilSUUID(), err @@ -29,7 +29,7 @@ func (svc *PessimismService) RunInvariantSession(params *models.InvRequestParams return core.NilSUUID(), err } - sUUID, err := svc.m.RunInvSession(deployCfg) + sUUID, err := svc.m.RunSession(deployCfg) if err != nil { return core.NilSUUID(), err } diff --git a/internal/api/service/invariant_test.go b/internal/api/service/heuristic_test.go similarity index 81% rename from internal/api/service/invariant_test.go rename to internal/api/service/heuristic_test.go index 4b9520b5..b2f6a5e0 100644 --- a/internal/api/service/invariant_test.go +++ b/internal/api/service/heuristic_test.go @@ -6,7 +6,7 @@ import ( "github.com/base-org/pessimism/internal/api/models" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" ) @@ -15,19 +15,19 @@ func testErr() error { return fmt.Errorf("test error") } -func Test_RunInvariantSession(t *testing.T) { +func Test_RunHeuristicSession(t *testing.T) { testSUUID := core.MakeSUUID(1, 1, 1) ctrl := gomock.NewController(t) - testCfg := &invariant.DeployConfig{} + testCfg := &heuristic.DeployConfig{} - defaultBody := &models.InvRequestBody{ + defaultBody := &models.SessionRequestBody{ Method: "run", - Params: models.InvRequestParams{ + Params: models.SessionRequestParams{ Network: "layer1", PType: "live", - InvType: "contract_event", + HeuristicType: "contract_event", StartHeight: nil, EndHeight: nil, SessionParams: nil, @@ -41,7 +41,7 @@ func Test_RunInvariantSession(t *testing.T) { testLogic func(*testing.T, *testSuite) }{ { - name: "Successful invariant session deployment", + name: "Successful heuristic session deployment", constructionLogic: func() *testSuite { ts := createTestSuite(ctrl) @@ -56,7 +56,7 @@ func Test_RunInvariantSession(t *testing.T) { Times(1) ts.mockSub.EXPECT(). - RunInvSession(testCfg). + RunSession(testCfg). Return(testSUUID, nil). Times(1) @@ -65,7 +65,7 @@ func Test_RunInvariantSession(t *testing.T) { testLogic: func(t *testing.T, ts *testSuite) { testParams := defaultBody.Clone() - actualSUUID, err := ts.apiSvc.ProcessInvariantRequest(testParams) + actualSUUID, err := ts.apiSvc.ProcessHeuristicRequest(testParams) assert.NoError(t, err) assert.Equal(t, testSUUID, actualSUUID) @@ -85,7 +85,7 @@ func Test_RunInvariantSession(t *testing.T) { testLogic: func(t *testing.T, ts *testSuite) { testParams := defaultBody.Clone() - actualSUUID, err := ts.apiSvc.ProcessInvariantRequest(testParams) + actualSUUID, err := ts.apiSvc.ProcessHeuristicRequest(testParams) assert.Error(t, err) assert.Equal(t, core.NilSUUID(), actualSUUID) @@ -111,14 +111,14 @@ func Test_RunInvariantSession(t *testing.T) { testLogic: func(t *testing.T, ts *testSuite) { testParams := defaultBody.Clone() - actualSUUID, err := ts.apiSvc.ProcessInvariantRequest(testParams) + actualSUUID, err := ts.apiSvc.ProcessHeuristicRequest(testParams) assert.Error(t, err) assert.Equal(t, core.NilSUUID(), actualSUUID) }, }, { - name: "Failure when running invariant session", + name: "Failure when running heuristic session", constructionLogic: func() *testSuite { ts := createTestSuite(ctrl) @@ -133,7 +133,7 @@ func Test_RunInvariantSession(t *testing.T) { Times(1) ts.mockSub.EXPECT(). - RunInvSession(testCfg). + RunSession(testCfg). Return(core.NilSUUID(), testErr()). Times(1) @@ -142,7 +142,7 @@ func Test_RunInvariantSession(t *testing.T) { testLogic: func(t *testing.T, ts *testSuite) { testParams := defaultBody.Clone() - actualSUUID, err := ts.apiSvc.ProcessInvariantRequest(testParams) + actualSUUID, err := ts.apiSvc.ProcessHeuristicRequest(testParams) assert.Error(t, err) assert.Equal(t, core.NilSUUID(), actualSUUID) diff --git a/internal/api/service/service.go b/internal/api/service/service.go index 84553cfd..f87b7419 100644 --- a/internal/api/service/service.go +++ b/internal/api/service/service.go @@ -12,8 +12,8 @@ import ( // Service ... Interface for API service type Service interface { - ProcessInvariantRequest(ir *models.InvRequestBody) (core.SUUID, error) - RunInvariantSession(params *models.InvRequestParams) (core.SUUID, error) + ProcessHeuristicRequest(ir *models.SessionRequestBody) (core.SUUID, error) + RunHeuristicSession(params *models.SessionRequestParams) (core.SUUID, error) CheckHealth() *models.HealthCheck CheckETHRPCHealth(n core.Network) bool diff --git a/internal/app/app.go b/internal/app/app.go index 9c95af98..a3f3056b 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -15,8 +15,8 @@ import ( "go.uber.org/zap" ) -// BootSession ... Application wrapper for InvRequestParams -type BootSession = models.InvRequestParams +// BootSession ... Application wrapper for SessionRequestParams +type BootSession = models.SessionRequestParams // Application ... Pessimism app struct type Application struct { @@ -89,12 +89,12 @@ func (a *Application) BootStrap(sessions []*BootSession) error { return err } - sUUID, err := a.sub.RunInvSession(deployCfg) + sUUID, err := a.sub.RunSession(deployCfg) if err != nil { return err } - logger.Info("invariant session started", + logger.Info("heuristic session started", zap.String(logging.SUUIDKey, sUUID.String())) } return nil diff --git a/internal/app/init.go b/internal/app/init.go index b71bda77..609a5ccc 100644 --- a/internal/app/init.go +++ b/internal/app/init.go @@ -78,7 +78,7 @@ func InitializeAlerting(ctx context.Context, cfg *config.Config) alert.Manager { } // InitializeETL ... Performs dependency injection to build etl struct -func InitializeETL(ctx context.Context, transit chan core.InvariantInput) pipeline.Manager { +func InitializeETL(ctx context.Context, transit chan core.HeuristicInput) pipeline.Manager { compRegistry := registry.NewRegistry() analyzer := pipeline.NewAnalyzer(compRegistry) store := pipeline.NewEtlStore() @@ -92,7 +92,7 @@ func InitializeEngine(ctx context.Context, transit chan core.Alert) engine.Manag store := engine.NewSessionStore() am := engine.NewAddressingMap() re := engine.NewHardCodedEngine() - it := e_registry.NewInvariantTable() + it := e_registry.NewHeuristicTable() return engine.NewManager(ctx, re, am, store, it, transit) } diff --git a/internal/core/alert.go b/internal/core/alert.go index 0f9cf252..bb2178d1 100644 --- a/internal/core/alert.go +++ b/internal/core/alert.go @@ -2,7 +2,7 @@ package core import "time" -// AlertingPolicy ... The alerting policy for an invariant session +// AlertingPolicy ... The alerting policy for a heuristic session // NOTE - This could be extended to support additional // policy metadata like criticality, etc. type AlertingPolicy struct { diff --git a/internal/core/config.go b/internal/core/config.go index f8c27a7d..a1f44cac 100644 --- a/internal/core/config.go +++ b/internal/core/config.go @@ -19,8 +19,8 @@ type SessionConfig struct { Network Network PT PipelineType AlertDest AlertDestination - Type InvariantType - Params *InvSessionParams + Type HeuristicType + Params *SessionParams } // PipelineConfig ... Configuration passed through to a pipeline constructor diff --git a/internal/core/constants.go b/internal/core/constants.go index 70e3d9aa..d7c0feff 100644 --- a/internal/core/constants.go +++ b/internal/core/constants.go @@ -83,18 +83,18 @@ const ( EthClientTimeout Timeouts = 20 // in seconds ) -// InvariantType ... Represents the type of invariant -type InvariantType uint8 +// HeuristicType ... Represents the type of heuristic +type HeuristicType uint8 const ( - BalanceEnforcement InvariantType = iota + 1 + BalanceEnforcement HeuristicType = iota + 1 ContractEvent WithdrawalEnforcement FaultDetector ) -// String ... Converts an invariant type to a string -func (it InvariantType) String() string { +// String ... Converts an heuristic type to a string +func (it HeuristicType) String() string { switch it { case BalanceEnforcement: return "balance_enforcement" @@ -113,8 +113,8 @@ func (it InvariantType) String() string { } } -// StringToInvariantType ... Converts a string to an invariant type -func StringToInvariantType(stringType string) InvariantType { +// StringToHeuristicType ... Converts a string to an heuristic type +func StringToHeuristicType(stringType string) HeuristicType { switch stringType { case "balance_enforcement": return BalanceEnforcement @@ -129,7 +129,7 @@ func StringToInvariantType(stringType string) InvariantType { return FaultDetector default: - return InvariantType(0) + return HeuristicType(0) } } diff --git a/internal/core/core.go b/internal/core/core.go index b95fdab9..c9408e5f 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -66,9 +66,9 @@ func NewTransitChannel() chan TransitData { return make(chan TransitData) } -// InvariantInput ... Standardized type used to supply +// HeuristicInput ... Standardized type used to supply // the Risk Engine -type InvariantInput struct { +type HeuristicInput struct { PUUID PUUID Input TransitData } @@ -77,25 +77,25 @@ type InvariantInput struct { // relay used to bind final ETL pipeline outputs to risk engine inputs type EngineInputRelay struct { pUUID PUUID - outChan chan InvariantInput + outChan chan HeuristicInput } // NewEngineRelay ... Initializer -func NewEngineRelay(pUUID PUUID, outChan chan InvariantInput) *EngineInputRelay { +func NewEngineRelay(pUUID PUUID, outChan chan HeuristicInput) *EngineInputRelay { return &EngineInputRelay{ pUUID: pUUID, outChan: outChan, } } -// RelayTransitData ... Creates invariant input from transit data to send to risk engine +// RelayTransitData ... Creates heuristic input from transit data to send to risk engine func (eir *EngineInputRelay) RelayTransitData(td TransitData) error { - invInput := InvariantInput{ + hi := HeuristicInput{ PUUID: eir.pUUID, Input: td, } - eir.outChan <- invInput + eir.outChan <- hi return nil } @@ -104,27 +104,27 @@ const ( NestedArgs = "args" ) -// InvSessionParams ... Parameters used to initialize an invariant session -type InvSessionParams struct { +// SessionParams ... Parameters used to initialize an heuristic session +type SessionParams struct { params map[string]any } -// Bytes ... Returns a marshalled byte array of the invariant session params -func (sp *InvSessionParams) Bytes() []byte { +// Bytes ... Returns a marshalled byte array of the heuristic session params +func (sp *SessionParams) Bytes() []byte { bytes, _ := json.Marshal(sp.params) return bytes } -// NewSessionParams ... Initializes invariant session params -func NewSessionParams() *InvSessionParams { - isp := &InvSessionParams{ +// NewSessionParams ... Initializes heuristic session params +func NewSessionParams() *SessionParams { + isp := &SessionParams{ params: make(map[string]any, 0), } isp.params[NestedArgs] = []any{} return isp } -func (sp *InvSessionParams) Value(key string) (any, error) { +func (sp *SessionParams) Value(key string) (any, error) { val, found := sp.params[key] if !found { return nil, fmt.Errorf("key %s not found", key) @@ -133,8 +133,8 @@ func (sp *InvSessionParams) Value(key string) (any, error) { return val, nil } -// Address ... Returns the address from the invariant session params -func (sp *InvSessionParams) Address() common.Address { +// Address ... Returns the address from the heuristic session params +func (sp *SessionParams) Address() common.Address { rawAddr, found := sp.params[AddressKey] if !found { return common.Address{0} @@ -148,21 +148,21 @@ func (sp *InvSessionParams) Address() common.Address { return common.HexToAddress(addr) } -// SetValue ... Sets a value in the invariant session params -func (sp *InvSessionParams) SetValue(key string, val any) { +// SetValue ... Sets a value in the heuristic session params +func (sp *SessionParams) SetValue(key string, val any) { sp.params[key] = val } -// SetNestedArg ... Sets a nested argument in the invariant session params +// SetNestedArg ... Sets a nested argument in the heuristic session params // unique nested key/value space -func (sp *InvSessionParams) SetNestedArg(arg interface{}) { +func (sp *SessionParams) SetNestedArg(arg interface{}) { args := sp.NestedArgs() args = append(args, arg) sp.params[NestedArgs] = args } -// NestedArgs ... Returns the nested arguments from the invariant session params -func (sp *InvSessionParams) NestedArgs() []any { +// NestedArgs ... Returns the nested arguments from the heuristic session params +func (sp *SessionParams) NestedArgs() []any { rawArgs, found := sp.params[NestedArgs] if !found { return []any{} @@ -176,8 +176,8 @@ func (sp *InvSessionParams) NestedArgs() []any { return args } -// Invalidation ... Represents an invalidation event -type Invalidation struct { +// Activation ... Represents an activation event +type Activation struct { TimeStamp time.Time Message string } diff --git a/internal/core/core_test.go b/internal/core/core_test.go index 3acc3213..b1f54872 100644 --- a/internal/core/core_test.go +++ b/internal/core/core_test.go @@ -28,7 +28,7 @@ func Test_TransitData(t *testing.T) { } func Test_EngineRelay(t *testing.T) { - outChan := make(chan core.InvariantInput) + outChan := make(chan core.HeuristicInput) eir := core.NewEngineRelay(core.NilPUUID(), outChan) dummyTD := core.NewTransitData(core.AccountBalance, nil) @@ -39,16 +39,16 @@ func Test_EngineRelay(t *testing.T) { _ = eir.RelayTransitData(dummyTD) }() - invInput := <-outChan + heurInput := <-outChan - assert.NotNil(t, invInput, "InvariantInput should not be nil") - assert.Equal(t, invInput.PUUID, core.NilPUUID(), "InvariantInput PUUID should be nil") - assert.Equal(t, invInput.Input, dummyTD, "InvariantInput Input should be dummyTD") + assert.NotNil(t, heurInput, "HeuristicInput should not be nil") + assert.Equal(t, heurInput.PUUID, core.NilPUUID(), "HeuristicInput PUUID should be nil") + assert.Equal(t, heurInput.Input, dummyTD, "HeuristicInput Input should be dummyTD") } -func Test_InvSessionParams(t *testing.T) { +func Test_SessionParams(t *testing.T) { isp := core.NewSessionParams() - assert.NotNil(t, isp, "InvSessionParams should not be nil") + assert.NotNil(t, isp, "SessionParams should not be nil") isp.SetValue("tst", "tst") val, err := isp.Value("tst") diff --git a/internal/core/id.go b/internal/core/id.go index 2239dc9c..1fddc104 100644 --- a/internal/core/id.go +++ b/internal/core/id.go @@ -71,24 +71,24 @@ func (uuid PUUID) NetworkType() Network { return Network(uuid.PID[1]) } -// InvSessionPID ... Invariant session Primary ID -type InvSessionPID [3]byte +// SessionPID ... Heuristic session Primary ID +type SessionPID [3]byte // Represents a non-deterministic ID that's assigned to -// every uniquely constructed invariant session +// every uniquely constructed heuristic session type SUUID struct { - PID InvSessionPID + PID SessionPID UUID UUID } // Network ... Returns network decoding from encoded pid byte -func (pid InvSessionPID) Network() Network { +func (pid SessionPID) Network() Network { return Network(pid[0]) } -// InvType ... Returns invariant type decoding from encoded pid byte -func (pid InvSessionPID) InvType() InvariantType { - return InvariantType(pid[2]) +// HeuristicType ... Returns heuristic type decoding from encoded pid byte +func (pid SessionPID) HeuristicType() HeuristicType { + return HeuristicType(pid[2]) } // NOTE - This is useful for error handling with functions that @@ -109,10 +109,10 @@ func NilPUUID() PUUID { } } -// NilSUUID ... Returns a zero'd out or empty invariant UUID +// NilSUUID ... Returns a zero'd out or empty heuristic UUID func NilSUUID() SUUID { return SUUID{ - PID: InvSessionPID{0}, + PID: SessionPID{0}, UUID: nilUUID(), } } @@ -154,12 +154,12 @@ func MakePUUID(pt PipelineType, firstCID, lastCID CUUID) PUUID { } } -// MakeSUUID ... Constructs an invariant PID sequence & random UUID -func MakeSUUID(n Network, pt PipelineType, invType InvariantType) SUUID { - pID := InvSessionPID{ +// MakeSUUID ... Constructs an heuristic PID sequence & random UUID +func MakeSUUID(n Network, pt PipelineType, ht HeuristicType) SUUID { + pID := SessionPID{ byte(n), byte(pt), - byte(invType), + byte(ht), } return SUUID{ @@ -207,16 +207,16 @@ func (uuid PUUID) String() string { ) } -// String ... Returns string representation of an invariant session PID -func (pid InvSessionPID) String() string { +// String ... Returns string representation of an heuristic session PID +func (pid SessionPID) String() string { return fmt.Sprintf("%s:%s:%s", Network(pid[0]).String(), PipelineType(pid[1]).String(), - InvariantType(pid[2]).String(), + HeuristicType(pid[2]).String(), ) } -// String ... Returns string representation of an invariant session UUID +// String ... Returns string representation of an heuristic session UUID func (uuid SUUID) String() string { return fmt.Sprintf("%s::%s", uuid.PID.String(), uuid.UUID.ShortString()) diff --git a/internal/core/id_test.go b/internal/core/id_test.go index 890a51ba..09f0b588 100644 --- a/internal/core/id_test.go +++ b/internal/core/id_test.go @@ -34,8 +34,8 @@ func Test_Pipeline_ID(t *testing.T) { assert.Equal(t, expectedStr, actualStr) } -func Test_InvSession_ID(t *testing.T) { - expectedID := core.InvSessionPID([3]byte{1, 2, 1}) +func Test_HeuristicSession_ID(t *testing.T) { + expectedID := core.SessionPID([3]byte{1, 2, 1}) actualID := core.MakeSUUID(1, 2, 1) assert.Equal(t, expectedID, actualID.PID) diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 798b4cad..521ec9a9 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -4,7 +4,7 @@ import ( "context" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/logging" "github.com/base-org/pessimism/internal/metrics" @@ -16,7 +16,7 @@ type Type int const ( HardCoded Type = iota + 1 - // NOTE: Dynamic invariant support is not implemented + // NOTE: Dynamic heuristic support is not implemented Dynamic ) @@ -24,11 +24,11 @@ const ( type RiskEngine interface { Type() Type Execute(context.Context, core.TransitData, - invariant.Invariant) (*core.Invalidation, bool) + heuristic.Heuristic) (*core.Activation, bool) } // hardCodedEngine ... Hard coded execution engine -// IE: native hardcoded application code for invariant implementation +// IE: native hardcoded application code for heuristic implementation type hardCodedEngine struct { // TODO: Add any engine specific fields here } @@ -43,22 +43,22 @@ func (e *hardCodedEngine) Type() Type { return HardCoded } -// Execute ... Executes the invariant +// Execute ... Executes the heuristic func (e *hardCodedEngine) Execute(ctx context.Context, data core.TransitData, - inv invariant.Invariant) (*core.Invalidation, bool) { + h heuristic.Heuristic) (*core.Activation, bool) { logger := logging.WithContext(ctx) - logger.Debug("Performing invariant invalidation", - zap.String("suuid", inv.SUUID().String())) - outcome, invalid, err := inv.Invalidate(data) + logger.Debug("Performing heuristic activation", + zap.String("suuid", h.SUUID().String())) + outcome, activated, err := h.Assess(data) if err != nil { - logger.Error("Failed to perform invalidation option for invariant", zap.Error(err)) + logger.Error("Failed to perform activation option for heuristic", zap.Error(err)) metrics.WithContext(ctx). - RecordInvExecutionError(inv) + RecordAssessmentError(h) return nil, false } - return outcome, invalid + return outcome, activated } diff --git a/internal/engine/engine_test.go b/internal/engine/engine_test.go index f8be24d2..1327b607 100644 --- a/internal/engine/engine_test.go +++ b/internal/engine/engine_test.go @@ -13,18 +13,18 @@ import ( ) type testSuite struct { - ctrl *gomock.Controller - re engine.RiskEngine - mockInv *mocks.MockInvariant + ctrl *gomock.Controller + re engine.RiskEngine + mockHeuristic *mocks.MockHeuristic } func createTestSuite(t *testing.T) *testSuite { ctrl := gomock.NewController(t) return &testSuite{ - ctrl: ctrl, - re: engine.NewHardCodedEngine(), - mockInv: mocks.NewMockInvariant(ctrl), + ctrl: ctrl, + re: engine.NewHardCodedEngine(), + mockHeuristic: mocks.NewMockHeuristic(ctrl), } } @@ -38,39 +38,39 @@ func Test_HardCodedEngine(t *testing.T) { test func(t *testing.T, ts *testSuite) }{ { - name: "Invalidation Failure From Error", + name: "Activation Failure From Error", test: func(t *testing.T, ts *testSuite) { td := core.TransitData{} - ts.mockInv.EXPECT().Invalidate(td). + ts.mockHeuristic.EXPECT().Assess(td). Return(nil, false, testErr()).Times(1) - ts.mockInv.EXPECT().SUUID(). + ts.mockHeuristic.EXPECT().SUUID(). Return(core.NilSUUID()).Times(1) - outcome, invalid := ts.re.Execute(context.Background(), td, ts.mockInv) + outcome, activated := ts.re.Execute(context.Background(), td, ts.mockHeuristic) assert.Nil(t, outcome) - assert.False(t, invalid) + assert.False(t, activated) }}, { - name: "Successful Invalidation", + name: "Successful Activation", test: func(t *testing.T, ts *testSuite) { td := core.TransitData{} - expectedOut := &core.Invalidation{ + expectedOut := &core.Activation{ Message: "20 inch blade on the Impala", } - ts.mockInv.EXPECT().Invalidate(td). + ts.mockHeuristic.EXPECT().Assess(td). Return(expectedOut, true, nil).Times(1) - ts.mockInv.EXPECT().SUUID(). + ts.mockHeuristic.EXPECT().SUUID(). Return(core.NilSUUID()).Times(1) - outcome, invalid := ts.re.Execute(context.Background(), td, ts.mockInv) + outcome, activated := ts.re.Execute(context.Background(), td, ts.mockHeuristic) assert.NotNil(t, outcome) - assert.True(t, invalid) + assert.True(t, activated) assert.Equal(t, expectedOut, outcome) }}, } diff --git a/internal/engine/invariant/config.go b/internal/engine/heuristic/config.go similarity index 59% rename from internal/engine/invariant/config.go rename to internal/engine/heuristic/config.go index 4fe6ea75..759a0f9a 100644 --- a/internal/engine/invariant/config.go +++ b/internal/engine/heuristic/config.go @@ -1,8 +1,8 @@ -package invariant +package heuristic import "github.com/base-org/pessimism/internal/core" -// DeployConfig ... Configuration for deploying an invariant session +// DeployConfig ... Configuration for deploying an heuristic session type DeployConfig struct { Stateful bool StateKey *core.StateKey @@ -11,8 +11,8 @@ type DeployConfig struct { PUUID core.PUUID Reuse bool - InvType core.InvariantType - InvParams *core.InvSessionParams + HeuristicType core.HeuristicType + Params *core.SessionParams AlertDest core.AlertDestination } diff --git a/internal/engine/heuristic/heuristic.go b/internal/engine/heuristic/heuristic.go new file mode 100644 index 00000000..6c0423ea --- /dev/null +++ b/internal/engine/heuristic/heuristic.go @@ -0,0 +1,82 @@ +//go:generate mockgen -package mocks --destination ../../mocks/heuristic.go . Heuristic + +package heuristic + +import ( + "fmt" + + "github.com/base-org/pessimism/internal/core" +) + +// ExecutionType ... Enum for execution type +type ExecutionType int + +const ( + // HardCoded ... Hard coded execution type (ie native application code) + HardCoded ExecutionType = iota + + invalidInTypeErr = "invalid input type provided for heuristic. expected %s, got %s" +) + +// Heuristic ... Interface that all heuristic implementations must adhere to +type Heuristic interface { + InputType() core.RegisterType + ValidateInput(core.TransitData) error + Assess(core.TransitData) (*core.Activation, bool, error) + SUUID() core.SUUID + SetSUUID(core.SUUID) +} + +// BaseHeuristicOpt ... Functional option for BaseHeuristic +type BaseHeuristicOpt = func(bi *BaseHeuristic) *BaseHeuristic + +// BaseHeuristic ... Base heuristic implementation +type BaseHeuristic struct { + sUUID core.SUUID + inType core.RegisterType +} + +// NewBaseHeuristic ... Initializer for BaseHeuristic +// This is a base type that's inherited by all hardcoded +// heuristic implementations +func NewBaseHeuristic(inType core.RegisterType, + opts ...BaseHeuristicOpt) Heuristic { + bi := &BaseHeuristic{ + inType: inType, + } + + for _, opt := range opts { + opt(bi) + } + + return bi +} + +// SUUID ... Returns the heuristic session UUID +func (bi *BaseHeuristic) SUUID() core.SUUID { + return bi.sUUID +} + +// InputType ... Returns the input type for the heuristic +func (bi *BaseHeuristic) InputType() core.RegisterType { + return bi.inType +} + +// Assess ... Determines if a heuristic activation has occurred; defaults to no-op +func (bi *BaseHeuristic) Assess(core.TransitData) (*core.Activation, bool, error) { + return nil, false, nil +} + +// SetSUUID ... Sets the heuristic session UUID +func (bi *BaseHeuristic) SetSUUID(sUUID core.SUUID) { + bi.sUUID = sUUID +} + +// ValidateInput ... Validates the input type for the heuristic +func (bi *BaseHeuristic) ValidateInput(td core.TransitData) error { + if td.Type != bi.InputType() { + return fmt.Errorf(invalidInTypeErr, bi.InputType(), td.Type) + } + + return nil +} diff --git a/internal/engine/invariant/invariant_test.go b/internal/engine/heuristic/heuristic_test.go similarity index 79% rename from internal/engine/invariant/invariant_test.go rename to internal/engine/heuristic/heuristic_test.go index 9f902f6d..d2030628 100644 --- a/internal/engine/invariant/invariant_test.go +++ b/internal/engine/heuristic/heuristic_test.go @@ -1,16 +1,16 @@ -package invariant_test +package heuristic_test import ( "testing" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/stretchr/testify/assert" ) -func Test_BaseInvariant(t *testing.T) { +func Test_BaseHeuristic(t *testing.T) { testSUUID := core.MakeSUUID(1, 1, 1) - bi := invariant.NewBaseInvariant(core.RegisterType(0)) + bi := heuristic.NewBaseHeuristic(core.RegisterType(0)) // Test SUUID bi.SetSUUID(testSUUID) diff --git a/internal/engine/invariant/invariant.go b/internal/engine/invariant/invariant.go deleted file mode 100644 index aca15a63..00000000 --- a/internal/engine/invariant/invariant.go +++ /dev/null @@ -1,82 +0,0 @@ -//go:generate mockgen -package mocks --destination ../../mocks/invariant.go . Invariant - -package invariant - -import ( - "fmt" - - "github.com/base-org/pessimism/internal/core" -) - -// ExecutionType ... Enum for execution type -type ExecutionType int - -const ( - // HardCoded ... Hard coded execution type (ie native application code) - HardCoded ExecutionType = iota - - invalidInTypeErr = "invalid input type provided for invariant. expected %s, got %s" -) - -// Invariant ... Interface that all invariant implementations must adhere to -type Invariant interface { - InputType() core.RegisterType - ValidateInput(core.TransitData) error - Invalidate(core.TransitData) (*core.Invalidation, bool, error) - SUUID() core.SUUID - SetSUUID(core.SUUID) -} - -// BaseInvariantOpt ... Functional option for BaseInvariant -type BaseInvariantOpt = func(bi *BaseInvariant) *BaseInvariant - -// BaseInvariant ... Base invariant implementation -type BaseInvariant struct { - sUUID core.SUUID - inType core.RegisterType -} - -// NewBaseInvariant ... Initializer for BaseInvariant -// This is a base type that's inherited by all hardcoded -// invariant implementations -func NewBaseInvariant(inType core.RegisterType, - opts ...BaseInvariantOpt) Invariant { - bi := &BaseInvariant{ - inType: inType, - } - - for _, opt := range opts { - opt(bi) - } - - return bi -} - -// SUUID ... Returns the invariant session UUID -func (bi *BaseInvariant) SUUID() core.SUUID { - return bi.sUUID -} - -// InputType ... Returns the input type for the invariant -func (bi *BaseInvariant) InputType() core.RegisterType { - return bi.inType -} - -// Invalidate ... Invalidates the invariant; defaults to no-op -func (bi *BaseInvariant) Invalidate(core.TransitData) (*core.Invalidation, bool, error) { - return nil, false, nil -} - -// SetSUUID ... Sets the invariant session UUID -func (bi *BaseInvariant) SetSUUID(sUUID core.SUUID) { - bi.sUUID = sUUID -} - -// ValidateInput ... Validates the input type for the invariant -func (bi *BaseInvariant) ValidateInput(td core.TransitData) error { - if td.Type != bi.InputType() { - return fmt.Errorf(invalidInTypeErr, bi.InputType(), td.Type) - } - - return nil -} diff --git a/internal/engine/manager.go b/internal/engine/manager.go index 49d120a9..456a87f9 100644 --- a/internal/engine/manager.go +++ b/internal/engine/manager.go @@ -8,7 +8,7 @@ import ( "time" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/engine/registry" "github.com/base-org/pessimism/internal/logging" "github.com/base-org/pessimism/internal/metrics" @@ -19,11 +19,11 @@ import ( // Manager ... Engine manager interface type Manager interface { - GetInputType(invType core.InvariantType) (core.RegisterType, error) - Transit() chan core.InvariantInput + GetInputType(ht core.HeuristicType) (core.RegisterType, error) + Transit() chan core.HeuristicInput - DeleteInvariantSession(core.SUUID) (core.SUUID, error) - DeployInvariantSession(cfg *invariant.DeployConfig) (core.SUUID, error) + DeleteHeuristicSession(core.SUUID) (core.SUUID, error) + DeployHeuristicSession(cfg *heuristic.DeployConfig) (core.SUUID, error) core.Subsystem } @@ -31,7 +31,7 @@ type Manager interface { /* NOTE - Manager will need to understand when pipeline changes occur that require remapping - invariant sessions to other pipelines + heuristic sessions to other pipelines */ // engineManager ... Engine management abstraction @@ -39,30 +39,30 @@ type engineManager struct { ctx context.Context cancel context.CancelFunc - etlIngress chan core.InvariantInput + etlIngress chan core.HeuristicInput alertOutgress chan core.Alert - metrics metrics.Metricer - engine RiskEngine - addresser AddressingMap - store SessionStore - invTable registry.InvariantTable + metrics metrics.Metricer + engine RiskEngine + addresser AddressingMap + store SessionStore + heuristics registry.HeuristicTable } // NewManager ... Initializer func NewManager(ctx context.Context, engine RiskEngine, addr AddressingMap, - store SessionStore, it registry.InvariantTable, alertOutgress chan core.Alert) Manager { + store SessionStore, it registry.HeuristicTable, alertOutgress chan core.Alert) Manager { ctx, cancel := context.WithCancel(ctx) em := &engineManager{ ctx: ctx, cancel: cancel, alertOutgress: alertOutgress, - etlIngress: make(chan core.InvariantInput), + etlIngress: make(chan core.HeuristicInput), engine: engine, addresser: addr, store: store, - invTable: it, + heuristics: it, metrics: metrics.WithContext(ctx), } @@ -70,19 +70,19 @@ func NewManager(ctx context.Context, engine RiskEngine, addr AddressingMap, } // Transit ... Returns inter-subsystem transit channel -func (em *engineManager) Transit() chan core.InvariantInput { +func (em *engineManager) Transit() chan core.HeuristicInput { return em.etlIngress } -// DeleteInvariantSession ... Deletes an invariant session -func (em *engineManager) DeleteInvariantSession(_ core.SUUID) (core.SUUID, error) { +// DeleteHeuristicSession ... Deletes an heuristic session +func (em *engineManager) DeleteHeuristicSession(_ core.SUUID) (core.SUUID, error) { return core.NilSUUID(), nil } // updateSharedState ... Updates the shared state store -// with contextual information about the invariant session +// with contextual information about the heuristic session // to the ETL (e.g. address, events) -func (em *engineManager) updateSharedState(invParams *core.InvSessionParams, +func (em *engineManager) updateSharedState(params *core.SessionParams, sk *core.StateKey, pUUID core.PUUID) error { err := sk.SetPUUID(pUUID) // PUUID already exists in key but is different than the one we want @@ -91,13 +91,13 @@ func (em *engineManager) updateSharedState(invParams *core.InvSessionParams, } // Use accessor method to insert entry into state store - err = state.InsertUnique(em.ctx, sk, invParams.Address().String()) + err = state.InsertUnique(em.ctx, sk, params.Address().String()) if err != nil { return err } if sk.IsNested() { // Nested addressing - for _, arg := range invParams.NestedArgs() { + for _, arg := range params.NestedArgs() { argStr, success := arg.(string) if !success { return fmt.Errorf("invalid event string") @@ -107,7 +107,7 @@ func (em *engineManager) updateSharedState(invParams *core.InvSessionParams, innerKey := &core.StateKey{ Nesting: false, Prefix: sk.Prefix, - ID: invParams.Address().String(), + ID: params.Address().String(), PUUID: &pUUID, } @@ -120,54 +120,54 @@ func (em *engineManager) updateSharedState(invParams *core.InvSessionParams, logging.WithContext(em.ctx).Debug("Setting to state store", zap.String(logging.PUUIDKey, pUUID.String()), - zap.String(logging.AddrKey, invParams.Address().String())) + zap.String(logging.AddrKey, params.Address().String())) return nil } -// DeployInvariantSession ... Deploys an invariant session to be processed by the engine -func (em *engineManager) DeployInvariantSession(cfg *invariant.DeployConfig) (core.SUUID, error) { - reg, exists := em.invTable[cfg.InvType] +// DeployHeuristicSession ... Deploys an heuristic session to be processed by the engine +func (em *engineManager) DeployHeuristicSession(cfg *heuristic.DeployConfig) (core.SUUID, error) { + reg, exists := em.heuristics[cfg.HeuristicType] if !exists { - return core.NilSUUID(), fmt.Errorf("invariant type %s not found", cfg.InvType) + return core.NilSUUID(), fmt.Errorf("heuristic type %s not found", cfg.HeuristicType) } - if reg.PrepareValidate != nil { // Prepare & validate the invariant params for stateful consumption - err := reg.PrepareValidate(cfg.InvParams) + if reg.PrepareValidate != nil { // Prepare & validate the heuristic params for stateful consumption + err := reg.PrepareValidate(cfg.Params) if err != nil { return core.NilSUUID(), err } } - // Build invariant instance using constructor function from register definition - inv, err := reg.Constructor(em.ctx, cfg.InvParams) + // Build heuristic instance using constructor function from register definition + h, err := reg.Constructor(em.ctx, cfg.Params) if err != nil { return core.NilSUUID(), err } - // Generate session UUID and set it to the invariant - sUUID := core.MakeSUUID(cfg.Network, cfg.PUUID.PipelineType(), cfg.InvType) - inv.SetSUUID(sUUID) + // Generate session UUID and set it to the heuristic + sUUID := core.MakeSUUID(cfg.Network, cfg.PUUID.PipelineType(), cfg.HeuristicType) + h.SetSUUID(sUUID) - err = em.store.AddInvSession(sUUID, cfg.PUUID, inv) + err = em.store.AddSession(sUUID, cfg.PUUID, h) if err != nil { return core.NilSUUID(), err } // Shared subsystem state management if cfg.Stateful { - err = em.addresser.Insert(cfg.InvParams.Address(), cfg.PUUID, sUUID) + err = em.addresser.Insert(cfg.Params.Address(), cfg.PUUID, sUUID) if err != nil { return core.NilSUUID(), err } - err = em.updateSharedState(cfg.InvParams, cfg.StateKey, cfg.PUUID) + err = em.updateSharedState(cfg.Params, cfg.StateKey, cfg.PUUID) if err != nil { return core.NilSUUID(), err } } - em.metrics.IncActiveInvariants(cfg.InvType, cfg.Network, cfg.PUUID.PipelineType()) + em.metrics.IncActiveHeuristics(cfg.HeuristicType, cfg.Network, cfg.PUUID.PipelineType()) return sUUID, nil } @@ -179,10 +179,10 @@ func (em *engineManager) EventLoop() error { for { select { case data := <-em.etlIngress: // ETL transit - logger.Debug("Received invariant input", + logger.Debug("Received heuristic input", zap.String("input", fmt.Sprintf("%+v", data))) - em.executeInvariants(em.ctx, data) + em.executeHeuristics(em.ctx, data) case <-em.ctx.Done(): // Shutdown logger.Debug("engineManager received shutdown signal") @@ -191,11 +191,11 @@ func (em *engineManager) EventLoop() error { } } -// GetInputType ... Returns the register input type for the invariant type -func (em *engineManager) GetInputType(invType core.InvariantType) (core.RegisterType, error) { - val, exists := em.invTable[invType] +// GetInputType ... Returns the register input type for the heuristic type +func (em *engineManager) GetInputType(ht core.HeuristicType) (core.RegisterType, error) { + val, exists := em.heuristics[ht] if !exists { - return 0, fmt.Errorf("invariant type %s not found", invType) + return 0, fmt.Errorf("heuristic type %s not found", ht) } return val.InputType, nil @@ -207,88 +207,88 @@ func (em *engineManager) Shutdown() error { return nil } -// executeInvariants ... Executes all invariants associated with the input etl pipeline -func (em *engineManager) executeInvariants(ctx context.Context, data core.InvariantInput) { - if data.Input.Addressed() { // Address based invariant - em.executeAddressInvariants(ctx, data) - } else { // Non Address based invariant - em.executeNonAddressInvariants(ctx, data) +// executeHeuristics ... Executes all heuristics associated with the input etl pipeline +func (em *engineManager) executeHeuristics(ctx context.Context, data core.HeuristicInput) { + if data.Input.Addressed() { // Address based heuristic + em.executeAddressHeuristics(ctx, data) + } else { // Non Address based heuristic + em.executeNonAddressHeuristics(ctx, data) } } -// executeAddressInvariants ... Executes all address specific invariants associated with the input etl pipeline -func (em *engineManager) executeAddressInvariants(ctx context.Context, data core.InvariantInput) { +// executeAddressHeuristics ... Executes all address specific heuristics associated with the input etl pipeline +func (em *engineManager) executeAddressHeuristics(ctx context.Context, data core.HeuristicInput) { logger := logging.WithContext(ctx) ids, err := em.addresser.GetSUUIDsByPair(data.Input.Address, data.PUUID) if err != nil { - logger.Error("Could not fetch invariants by address:pipeline", + logger.Error("Could not fetch heuristics by address:pipeline", zap.Error(err), zap.String(logging.PUUIDKey, data.PUUID.String())) return } for _, sUUID := range ids { - inv, err := em.store.GetInstanceByUUID(sUUID) + h, err := em.store.GetInstanceByUUID(sUUID) if err != nil { - logger.Error("Could not session by invariant sUUID", + logger.Error("Could not session by heuristic sUUID", zap.Error(err), zap.String(logging.PUUIDKey, sUUID.String())) continue } - em.executeInvariant(ctx, data, inv) + em.executeHeuristic(ctx, data, h) } } -// executeNonAddressInvariants ... Executes all non address specific invariants associated with the input etl pipeline -func (em *engineManager) executeNonAddressInvariants(ctx context.Context, data core.InvariantInput) { +// executeNonAddressHeuristics ... Executes all non address specific heuristics associated with the input etl pipeline +func (em *engineManager) executeNonAddressHeuristics(ctx context.Context, data core.HeuristicInput) { logger := logging.WithContext(ctx) // Fetch all session UUIDs associated with the pipeline sUUIDs, err := em.store.GetSUUIDsByPUUID(data.PUUID) if err != nil { - logger.Error("Could not fetch invariants for pipeline", + logger.Error("Could not fetch heuristics for pipeline", zap.Error(err), zap.String(logging.PUUIDKey, data.PUUID.String())) } - // Fetch all invariants for a slice of SUUIDs - invs, err := em.store.GetInstancesByUUIDs(sUUIDs) + // Fetch all heuristics for a slice of SUUIDs + heuristics, err := em.store.GetInstancesByUUIDs(sUUIDs) if err != nil { - logger.Error("Could not fetch invariants for pipeline", + logger.Error("Could not fetch heuristics for pipeline", zap.Error(err), zap.String(logging.PUUIDKey, data.PUUID.String())) } - for _, inv := range invs { // Execute all invariants associated with the pipeline - em.executeInvariant(ctx, data, inv) + for _, h := range heuristics { // Execute all heuristics associated with the pipeline + em.executeHeuristic(ctx, data, h) } } -// executeInvariant ... Executes a single invariant using the risk engine -func (em *engineManager) executeInvariant(ctx context.Context, data core.InvariantInput, inv invariant.Invariant) { +// executeHeuristic ... Executes a single heuristic using the risk engine +func (em *engineManager) executeHeuristic(ctx context.Context, data core.HeuristicInput, h heuristic.Heuristic) { logger := logging.WithContext(ctx) start := time.Now() - // Execute invariant using risk engine and return alert if invalidation occurs - outcome, invalidated := em.engine.Execute(ctx, data.Input, inv) + // Execute heuristic using risk engine and return alert if activation occurs + outcome, activated := em.engine.Execute(ctx, data.Input, h) - em.metrics.RecordInvariantRun(inv) - em.metrics.RecordInvExecutionTime(inv, float64(time.Since(start).Nanoseconds())) + em.metrics.RecordHeuristicRun(h) + em.metrics.RecordInvExecutionTime(h, float64(time.Since(start).Nanoseconds())) - if invalidated { + if activated { // Generate & send alert alert := core.Alert{ Timestamp: outcome.TimeStamp, - SUUID: inv.SUUID(), + SUUID: h.SUUID(), Content: outcome.Message, PUUID: data.PUUID, Ptype: data.PUUID.PipelineType(), } - logger.Warn("Invariant alert", - zap.String(logging.SUUIDKey, inv.SUUID().String()), + logger.Warn("Heuristic alert", + zap.String(logging.SUUIDKey, h.SUUID().String()), zap.String("message", outcome.Message)) em.alertOutgress <- alert diff --git a/internal/engine/manager_test.go b/internal/engine/manager_test.go index b9bc05f4..ebc1a49d 100644 --- a/internal/engine/manager_test.go +++ b/internal/engine/manager_test.go @@ -8,7 +8,7 @@ import ( "github.com/base-org/pessimism/internal/core" "github.com/base-org/pessimism/internal/engine" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/engine/registry" "github.com/base-org/pessimism/internal/state" "github.com/ethereum/go-ethereum/common" @@ -29,7 +29,7 @@ func Test_EventLoop(t *testing.T) { engine.NewHardCodedEngine(), engine.NewAddressingMap(), engine.NewSessionStore(), - registry.NewInvariantTable(), + registry.NewHeuristicTable(), alertChan, ) @@ -52,23 +52,23 @@ func Test_EventLoop(t *testing.T) { isp.SetValue("address", common.HexToAddress("0x69").String()) isp.SetValue("upper", 420) - // Deploy invariant session - deployCfg := &invariant.DeployConfig{ - InvType: core.BalanceEnforcement, - Network: core.Layer1, - Stateful: true, - StateKey: &core.StateKey{}, - AlertDest: core.Slack, - InvParams: isp, - PUUID: testPUUID, + // Deploy heuristic session + deployCfg := &heuristic.DeployConfig{ + HeuristicType: core.BalanceEnforcement, + Network: core.Layer1, + Stateful: true, + StateKey: &core.StateKey{}, + AlertDest: core.Slack, + Params: isp, + PUUID: testPUUID, } - suuid, err := em.DeployInvariantSession(deployCfg) + suuid, err := em.DeployHeuristicSession(deployCfg) assert.NoError(t, err) assert.NotNil(t, suuid) - // Construct invariant input - invInput := core.InvariantInput{ + // Construct heuristic input + hi := core.HeuristicInput{ PUUID: testPUUID, Input: core.TransitData{ Type: core.AccountBalance, @@ -77,8 +77,8 @@ func Test_EventLoop(t *testing.T) { }, } - // Send invariant input to event loop - ingress <- invInput + // Send heuristic input to event loop + ingress <- hi ticker := time.NewTicker(1 * time.Second) // Receive alert from event loop diff --git a/internal/engine/registry/balance_enforce.go b/internal/engine/registry/balance_enforce.go index a6bda7a0..91b25924 100644 --- a/internal/engine/registry/balance_enforce.go +++ b/internal/engine/registry/balance_enforce.go @@ -6,28 +6,28 @@ import ( "time" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/logging" "go.uber.org/zap" ) -// BalanceInvConfig ... Configuration for the balance invariant +// BalanceInvConfig ... Configuration for the balance heuristic type BalanceInvConfig struct { Address string `json:"address"` UpperBound *float64 `json:"upper"` LowerBound *float64 `json:"lower"` } -// Unmarshal ... Converts a general config to a balance invariant config -func (bi *BalanceInvConfig) Unmarshal(isp *core.InvSessionParams) error { +// Unmarshal ... Converts a general config to a balance heuristic config +func (bi *BalanceInvConfig) Unmarshal(isp *core.SessionParams) error { return json.Unmarshal(isp.Bytes(), &bi) } -// BalanceInvariant ... -type BalanceInvariant struct { +// BalanceHeuristic ... +type BalanceHeuristic struct { cfg *BalanceInvConfig - invariant.Invariant + heuristic.Heuristic } // reportMsg ... Message to be sent to the alerting subsystem @@ -40,18 +40,18 @@ const reportMsg = ` Session Address: %s ` -// NewBalanceInvariant ... Initializer -func NewBalanceInvariant(cfg *BalanceInvConfig) (invariant.Invariant, error) { - return &BalanceInvariant{ +// NewBalanceHeuristic ... Initializer +func NewBalanceHeuristic(cfg *BalanceInvConfig) (heuristic.Heuristic, error) { + return &BalanceHeuristic{ cfg: cfg, - Invariant: invariant.NewBaseInvariant(core.AccountBalance), + Heuristic: heuristic.NewBaseHeuristic(core.AccountBalance), }, nil } -// Invalidate ... Checks if the balance is within the bounds +// Assess ... Checks if the balance is within the bounds // specified in the config -func (bi *BalanceInvariant) Invalidate(td core.TransitData) (*core.Invalidation, bool, error) { - logging.NoContext().Debug("Checking invalidation for balance invariant", zap.String("data", fmt.Sprintf("%v", td))) +func (bi *BalanceHeuristic) Assess(td core.TransitData) (*core.Activation, bool, error) { + logging.NoContext().Debug("Checking activation for balance heuristic", zap.String("data", fmt.Sprintf("%v", td))) // 1. Validate and extract balance input err := bi.ValidateInput(td) @@ -64,22 +64,22 @@ func (bi *BalanceInvariant) Invalidate(td core.TransitData) (*core.Invalidation, return nil, false, fmt.Errorf(couldNotCastErr, "float64") } - invalidated := false + activated := false - // 2. Invalidate if balance > upper bound + // 2. Assess if balance > upper bound if bi.cfg.UpperBound != nil && *bi.cfg.UpperBound < balance { - invalidated = true + activated = true } - // 3. Invalidate if balance < lower bound + // 3. Assess if balance < lower bound if bi.cfg.LowerBound != nil && *bi.cfg.LowerBound > balance { - invalidated = true + activated = true } - /// 4. Generate invalidation outcome if invalidated - if invalidated { + /// 4. Generate activation outcome if activated + if activated { var upper, lower string if bi.cfg.UpperBound != nil { @@ -94,7 +94,7 @@ func (bi *BalanceInvariant) Invalidate(td core.TransitData) (*core.Invalidation, lower = "-∞" } - return &core.Invalidation{ + return &core.Activation{ TimeStamp: time.Now(), Message: fmt.Sprintf(reportMsg, balance, upper, lower, @@ -102,6 +102,6 @@ func (bi *BalanceInvariant) Invalidate(td core.TransitData) (*core.Invalidation, }, true, nil } - // No invalidation + // No activation return nil, false, nil } diff --git a/internal/engine/registry/balance_enforce_test.go b/internal/engine/registry/balance_enforce_test.go index 88f965d2..52c21103 100644 --- a/internal/engine/registry/balance_enforce_test.go +++ b/internal/engine/registry/balance_enforce_test.go @@ -8,11 +8,11 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_Balance_Invalidate(t *testing.T) { +func Test_Balance_Assess(t *testing.T) { upper := float64(5) lower := float64(1) - bi, err := registry.NewBalanceInvariant( + bi, err := registry.NewBalanceHeuristic( ®istry.BalanceInvConfig{ Address: "0x123", UpperBound: &upper, @@ -21,33 +21,33 @@ func Test_Balance_Invalidate(t *testing.T) { assert.NoError(t, err) - // No invalidation + // No activation testData1 := core.TransitData{ Type: core.AccountBalance, Value: float64(3), } - _, inval, err := bi.Invalidate(testData1) + _, activated, err := bi.Assess(testData1) assert.NoError(t, err) - assert.False(t, inval) + assert.False(t, activated) - // Upper bound invalidation + // Upper bound activation testData2 := core.TransitData{ Type: core.AccountBalance, Value: float64(6), } - _, inval, err = bi.Invalidate(testData2) + _, activated, err = bi.Assess(testData2) assert.NoError(t, err) - assert.True(t, inval) + assert.True(t, activated) - // Lower bound invalidation + // Lower bound activation testData3 := core.TransitData{ Type: core.AccountBalance, Value: float64(0.1), } - _, inval, err = bi.Invalidate(testData3) + _, activated, err = bi.Assess(testData3) assert.NoError(t, err) - assert.True(t, inval) + assert.True(t, activated) } diff --git a/internal/engine/registry/constants.go b/internal/engine/registry/constants.go index 803a02fc..1ba3503c 100644 --- a/internal/engine/registry/constants.go +++ b/internal/engine/registry/constants.go @@ -2,7 +2,7 @@ package registry const ( // Error constant strings - invalidAddrErr = "invalid address provided for invariant. expected %s, got %s" + invalidAddrErr = "invalid address provided for heuristic. expected %s, got %s" couldNotCastErr = "could not cast transit data value to %s type" noNestedArgsErr = "no nested args found in session params" zeroAddressErr = "provided address cannot be the zero address" diff --git a/internal/engine/registry/contract_event.go b/internal/engine/registry/contract_event.go index b431e4d8..76b17f8a 100644 --- a/internal/engine/registry/contract_event.go +++ b/internal/engine/registry/contract_event.go @@ -5,30 +5,30 @@ import ( "fmt" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" ) -// EventInvConfig ... Configuration for the event invariant +// EventInvConfig ... Configuration for the event heuristic type EventInvConfig struct { ContractName string `json:"contract_name"` Address string `json:"address"` Sigs []string `json:"args"` } -// Unmarshal ... Converts a general config to an event invariant config -func (eic *EventInvConfig) Unmarshal(isp *core.InvSessionParams) error { +// Unmarshal ... Converts a general config to an event heuristic config +func (eic *EventInvConfig) Unmarshal(isp *core.SessionParams) error { return json.Unmarshal(isp.Bytes(), &eic) } -// EventInvariant ... -type EventInvariant struct { +// EventHeuristic ... +type EventHeuristic struct { cfg *EventInvConfig sigs []common.Hash - invariant.Invariant + heuristic.Heuristic } // eventReportMsg ... Message to be sent to the alerting system @@ -41,25 +41,25 @@ const eventReportMsg = ` Event: %s ` -// NewEventInvariant ... Initializer -func NewEventInvariant(cfg *EventInvConfig) invariant.Invariant { +// NewEventHeuristic ... Initializer +func NewEventHeuristic(cfg *EventInvConfig) heuristic.Heuristic { var sigs []common.Hash for _, sig := range cfg.Sigs { sigs = append(sigs, crypto.Keccak256Hash([]byte(sig))) } - return &EventInvariant{ + return &EventHeuristic{ cfg: cfg, sigs: sigs, - Invariant: invariant.NewBaseInvariant(core.EventLog), + Heuristic: heuristic.NewBaseHeuristic(core.EventLog), } } -// Invalidate ... Checks if the balance is within the bounds +// Assess ... Checks if the balance is within the bounds // specified in the config -func (ei *EventInvariant) Invalidate(td core.TransitData) (*core.Invalidation, bool, error) { +func (ei *EventHeuristic) Assess(td core.TransitData) (*core.Activation, bool, error) { // 1. Validate and extract the log event from the transit data err := ei.ValidateInput(td) if err != nil { @@ -76,19 +76,19 @@ func (ei *EventInvariant) Invalidate(td core.TransitData) (*core.Invalidation, b } // 2. Check if the log event signature is in the list of signatures - invalidated := false + activated := false for _, sig := range ei.sigs { if log.Topics[0] == sig { - invalidated = true + activated = true break } } - if !invalidated { + if !activated { return nil, false, nil } - return &core.Invalidation{ + return &core.Activation{ Message: fmt.Sprintf(eventReportMsg, ei.cfg.ContractName, log.Address, log.TxHash.Hex(), ei.cfg.Sigs[0]), }, true, nil } diff --git a/internal/engine/registry/contract_event_test.go b/internal/engine/registry/contract_event_test.go index fb0922ac..f2c48f3e 100644 --- a/internal/engine/registry/contract_event_test.go +++ b/internal/engine/registry/contract_event_test.go @@ -11,15 +11,15 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_Event_Log_Invariant(t *testing.T) { +func Test_Event_Log_Heuristic(t *testing.T) { var tests = []struct { name string function func(t *testing.T, cfg *registry.EventInvConfig) }{ { - name: "Successful Invalidation", + name: "Successful Activation", function: func(t *testing.T, cfg *registry.EventInvConfig) { - ei := registry.NewEventInvariant( + ei := registry.NewEventHeuristic( ®istry.EventInvConfig{ Address: "0x0000000000000000000000000000000000000420", ContractName: "0x69", @@ -36,17 +36,17 @@ func Test_Event_Log_Invariant(t *testing.T) { }, } - outcome, invalid, err := ei.Invalidate(td) + outcome, activated, err := ei.Assess(td) assert.NoError(t, err) - assert.True(t, invalid) + assert.True(t, activated) assert.NotNil(t, outcome) }, }, { - name: "Error Invalidation Due to Mismatched Addresses", + name: "Error Activation Due to Mismatched Addresses", function: func(t *testing.T, cfg *registry.EventInvConfig) { - ei := registry.NewEventInvariant( + ei := registry.NewEventHeuristic( ®istry.EventInvConfig{ Address: "0x0000000000000000000000000000000000000420", ContractName: "0x69", @@ -63,17 +63,17 @@ func Test_Event_Log_Invariant(t *testing.T) { }, } - outcome, invalid, err := ei.Invalidate(td) + outcome, activated, err := ei.Assess(td) assert.Error(t, err) - assert.False(t, invalid) + assert.False(t, activated) assert.Nil(t, outcome) }, }, { - name: "No Invalidation Due to Missing Signature", + name: "No Activation Due to Missing Signature", function: func(t *testing.T, cfg *registry.EventInvConfig) { - ei := registry.NewEventInvariant( + ei := registry.NewEventHeuristic( ®istry.EventInvConfig{ Address: "0x0000000000000000000000000000000000000420", ContractName: "0x69", @@ -90,10 +90,10 @@ func Test_Event_Log_Invariant(t *testing.T) { }, } - outcome, invalid, err := ei.Invalidate(td) + outcome, activated, err := ei.Assess(td) assert.NoError(t, err) - assert.False(t, invalid) + assert.False(t, activated) assert.Nil(t, outcome) }, }, diff --git a/internal/engine/registry/fault_detector.go b/internal/engine/registry/fault_detector.go index 68e4f230..475b30c1 100644 --- a/internal/engine/registry/fault_detector.go +++ b/internal/engine/registry/fault_detector.go @@ -8,7 +8,7 @@ import ( "github.com/base-org/pessimism/internal/client" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/logging" "github.com/base-org/pessimism/internal/metrics" "github.com/ethereum-optimism/optimism/op-bindings/bindings" @@ -30,14 +30,14 @@ const faultDetectMsg = ` Transaction Hash: %s ` -// FaultDetectorCfg ... Configuration for the fault detector invariant +// FaultDetectorCfg ... Configuration for the fault detector heuristic type FaultDetectorCfg struct { L2OutputOracle string `json:"l2_output_address"` L2ToL1Address string `json:"l2_to_l1_address"` } -// Unmarshal ... Converts a general config to a fault detector invariant config -func (fdc *FaultDetectorCfg) Unmarshal(isp *core.InvSessionParams) error { +// Unmarshal ... Converts a general config to a fault detector heuristic config +func (fdc *FaultDetectorCfg) Unmarshal(isp *core.SessionParams) error { return json.Unmarshal(isp.Bytes(), &fdc) } @@ -69,11 +69,11 @@ type faultDetectorInv struct { l2GethClient client.GethClient stats metrics.Metricer - invariant.Invariant + heuristic.Heuristic } // NewFaultDetector ... Initializer -func NewFaultDetector(ctx context.Context, cfg *FaultDetectorCfg) (invariant.Invariant, error) { +func NewFaultDetector(ctx context.Context, cfg *FaultDetectorCfg) (heuristic.Heuristic, error) { l2Client, err := client.FromContext(ctx, core.Layer2) if err != nil { return nil, err @@ -108,13 +108,13 @@ func NewFaultDetector(ctx context.Context, cfg *FaultDetectorCfg) (invariant.Inv l2Client: l2Client, l2GethClient: l2Geth, - Invariant: invariant.NewBaseInvariant(core.EventLog), + Heuristic: heuristic.NewBaseHeuristic(core.EventLog), }, nil } -// Invalidate ... Performs the fault detection invariant logic -func (fd *faultDetectorInv) Invalidate(td core.TransitData) (*core.Invalidation, bool, error) { - logging.NoContext().Debug("Checking invalidation for fault detector invariant", +// Assess ... Performs the fault detection heuristic logic +func (fd *faultDetectorInv) Assess(td core.TransitData) (*core.Activation, bool, error) { + logging.NoContext().Debug("Checking activation for fault detector heuristic", zap.String("data", fmt.Sprintf("%v", td))) // 1. Validate and extract data input @@ -163,9 +163,9 @@ func (fd *faultDetectorInv) Invalidate(td core.TransitData) (*core.Invalidation, actualStateRoot := output.OutputRoot - // 6. Compare the expected state root with the actual state root; if they are not equal, then invalidate + // 6. Compare the expected state root with the actual state root; if they are not equal, then activate if expectedStateRoot != actualStateRoot { - return &core.Invalidation{ + return &core.Activation{ TimeStamp: time.Now(), Message: fmt.Sprintf(faultDetectMsg, fd.cfg.L2OutputOracle, fd.cfg.L2ToL1Address, fd.SUUID(), log.TxHash), }, true, nil diff --git a/internal/engine/registry/fault_detector_test.go b/internal/engine/registry/fault_detector_test.go index c7b53ac7..fcd02ad7 100644 --- a/internal/engine/registry/fault_detector_test.go +++ b/internal/engine/registry/fault_detector_test.go @@ -7,7 +7,7 @@ import ( "github.com/base-org/pessimism/internal/app" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/engine/registry" "github.com/base-org/pessimism/internal/mocks" "github.com/ethereum/go-ethereum/common" @@ -28,7 +28,7 @@ type fdTestSuite struct { mockEthClient *mocks.MockEthClient mockGethClient *mocks.MockGethClient - fd invariant.Invariant + fd heuristic.Heuristic } func createFdTestSuite(t *testing.T) *fdTestSuite { @@ -86,7 +86,7 @@ func Test_FaultDetector(t *testing.T) { Value: testLog, } - outcome, pass, err := ts.fd.Invalidate(td) + outcome, pass, err := ts.fd.Assess(td) assert.Nil(t, outcome) assert.False(t, pass) assert.Error(t, err) @@ -113,7 +113,7 @@ func Test_FaultDetector(t *testing.T) { Value: testLog, } - outcome, pass, err := ts.fd.Invalidate(td) + outcome, pass, err := ts.fd.Assess(td) assert.Nil(t, outcome) assert.False(t, pass) assert.Error(t, err) @@ -121,7 +121,7 @@ func Test_FaultDetector(t *testing.T) { }, }, { - name: "Invalidation occurs when provided an invalid proof response", + name: "Activation occurs when provided an invalid proof response", constructor: createFdTestSuite, testFunc: func(t *testing.T, ts *fdTestSuite) { @@ -149,7 +149,7 @@ func Test_FaultDetector(t *testing.T) { Value: testLog, } - outcome, pass, err := ts.fd.Invalidate(td) + outcome, pass, err := ts.fd.Assess(td) assert.NotNil(t, outcome) assert.True(t, pass) assert.NoError(t, err) diff --git a/internal/engine/registry/registry.go b/internal/engine/registry/registry.go index 91ebf8ba..938d3c0e 100644 --- a/internal/engine/registry/registry.go +++ b/internal/engine/registry/registry.go @@ -5,25 +5,25 @@ import ( "fmt" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/logging" "github.com/ethereum/go-ethereum/common" ) -// InvariantTable ... Invariant table -type InvariantTable map[core.InvariantType]*InvRegister +// HeuristicTable ... Heuristic table +type HeuristicTable map[core.HeuristicType]*InvRegister -// InvRegister ... Invariant register struct +// InvRegister ... Heuristic register struct type InvRegister struct { - PrepareValidate func(*core.InvSessionParams) error + PrepareValidate func(*core.SessionParams) error Policy core.ChainSubscription InputType core.RegisterType - Constructor func(ctx context.Context, isp *core.InvSessionParams) (invariant.Invariant, error) + Constructor func(ctx context.Context, isp *core.SessionParams) (heuristic.Heuristic, error) } -// NewInvariantTable ... Initializer -func NewInvariantTable() InvariantTable { - tbl := map[core.InvariantType]*InvRegister{ +// NewHeuristicTable ... Initializer +func NewHeuristicTable() HeuristicTable { + tbl := map[core.HeuristicType]*InvRegister{ core.BalanceEnforcement: { PrepareValidate: ValidateAddressing, Policy: core.BothNetworks, @@ -53,8 +53,8 @@ func NewInvariantTable() InvariantTable { return tbl } -// constructEventInv ... Constructs an event invariant instance -func constructEventInv(_ context.Context, isp *core.InvSessionParams) (invariant.Invariant, error) { +// constructEventInv ... Constructs an event heuristic instance +func constructEventInv(_ context.Context, isp *core.SessionParams) (heuristic.Heuristic, error) { cfg := &EventInvConfig{} err := cfg.Unmarshal(isp) @@ -62,11 +62,11 @@ func constructEventInv(_ context.Context, isp *core.InvSessionParams) (invariant return nil, err } - return NewEventInvariant(cfg), nil + return NewEventHeuristic(cfg), nil } -// constructBalanceEnforcement ... Constructs a balance invariant instance -func constructBalanceEnforcement(_ context.Context, isp *core.InvSessionParams) (invariant.Invariant, error) { +// constructBalanceEnforcement ... Constructs a balance heuristic instance +func constructBalanceEnforcement(_ context.Context, isp *core.SessionParams) (heuristic.Heuristic, error) { cfg := &BalanceInvConfig{} err := cfg.Unmarshal(isp) @@ -74,11 +74,11 @@ func constructBalanceEnforcement(_ context.Context, isp *core.InvSessionParams) return nil, err } - return NewBalanceInvariant(cfg) + return NewBalanceHeuristic(cfg) } -// constructFaultDetector ... Constructs a fault detector invariant instance -func constructFaultDetector(ctx context.Context, isp *core.InvSessionParams) (invariant.Invariant, error) { +// constructFaultDetector ... Constructs a fault detector heuristic instance +func constructFaultDetector(ctx context.Context, isp *core.SessionParams) (heuristic.Heuristic, error) { cfg := &FaultDetectorCfg{} err := cfg.Unmarshal(isp) @@ -89,8 +89,8 @@ func constructFaultDetector(ctx context.Context, isp *core.InvSessionParams) (in return NewFaultDetector(ctx, cfg) } -// constructWithdrawalEnforce ... Constructs a withdrawal enforcement invariant instance -func constructWithdrawalEnforce(ctx context.Context, isp *core.InvSessionParams) (invariant.Invariant, error) { +// constructWithdrawalEnforce ... Constructs a withdrawal enforcement heuristic instance +func constructWithdrawalEnforce(ctx context.Context, isp *core.SessionParams) (heuristic.Heuristic, error) { cfg := &WithdrawalEnforceCfg{} err := cfg.Unmarshal(isp) @@ -102,7 +102,7 @@ func constructWithdrawalEnforce(ctx context.Context, isp *core.InvSessionParams) } // ValidateEventTracking ... Ensures that an address and nested args exist in the session params -func ValidateEventTracking(cfg *core.InvSessionParams) error { +func ValidateEventTracking(cfg *core.SessionParams) error { err := ValidateAddressing(cfg) if err != nil { return err @@ -112,7 +112,7 @@ func ValidateEventTracking(cfg *core.InvSessionParams) error { } // ValidateAddressing ... Ensures that an address exists in the session params -func ValidateAddressing(cfg *core.InvSessionParams) error { +func ValidateAddressing(cfg *core.SessionParams) error { nilAddr := common.Address{0} if cfg.Address() == nilAddr { return fmt.Errorf(zeroAddressErr) @@ -122,7 +122,7 @@ func ValidateAddressing(cfg *core.InvSessionParams) error { } // ValidateTopicsExist ... Ensures that some nested args exist in the session params -func ValidateTopicsExist(cfg *core.InvSessionParams) error { +func ValidateTopicsExist(cfg *core.SessionParams) error { if len(cfg.NestedArgs()) == 0 { return fmt.Errorf(noNestedArgsErr) } @@ -130,7 +130,7 @@ func ValidateTopicsExist(cfg *core.InvSessionParams) error { } // ValidateNoTopicsExist ... Ensures that no nested args exist in the session params -func ValidateNoTopicsExist(cfg *core.InvSessionParams) error { +func ValidateNoTopicsExist(cfg *core.SessionParams) error { if len(cfg.NestedArgs()) != 0 { return fmt.Errorf(noNestedArgsErr) } @@ -141,7 +141,7 @@ func ValidateNoTopicsExist(cfg *core.InvSessionParams) error { // and performs a "hack" operation to set the address key as the l2tol1MessagePasser // address for upstream ETL components (ie. event log) to know which L1 address to // query for events -func WithdrawEnforcePrepare(cfg *core.InvSessionParams) error { +func WithdrawEnforcePrepare(cfg *core.SessionParams) error { l1Portal, err := cfg.Value(core.L1Portal) if err != nil { return err @@ -167,7 +167,7 @@ func WithdrawEnforcePrepare(cfg *core.InvSessionParams) error { // FaultDetectionPrepare ... Configures the session params with the appropriate // address key and nested args for the ETL to subscribe to L2OutputOracle events -func FaultDetectionPrepare(cfg *core.InvSessionParams) error { +func FaultDetectionPrepare(cfg *core.SessionParams) error { l2OutputOracle, err := cfg.Value(core.L2OutputOracle) if err != nil { return err diff --git a/internal/engine/registry/registsry_test.go b/internal/engine/registry/registsry_test.go index f91d7be4..64874619 100644 --- a/internal/engine/registry/registsry_test.go +++ b/internal/engine/registry/registsry_test.go @@ -55,14 +55,14 @@ func Test_WithdrawEnforcePreprocess(t *testing.T) { } func Test_InvTable(t *testing.T) { - tabl := registry.NewInvariantTable() + tabl := registry.NewHeuristicTable() - for key, inv := range tabl { + for key, h := range tabl { t.Run(key.String(), func(t *testing.T) { - assert.NotNil(t, inv.Constructor) - assert.NotNil(t, inv.PrepareValidate) - assert.NotEqual(t, inv.InputType.String(), core.UnknownType) + assert.NotNil(t, h.Constructor) + assert.NotNil(t, h.PrepareValidate) + assert.NotEqual(t, h.InputType.String(), core.UnknownType) }) } } diff --git a/internal/engine/registry/withdrawal_enforce.go b/internal/engine/registry/withdrawal_enforce.go index 23ef062c..b5e8a4ea 100644 --- a/internal/engine/registry/withdrawal_enforce.go +++ b/internal/engine/registry/withdrawal_enforce.go @@ -8,7 +8,7 @@ import ( "github.com/base-org/pessimism/internal/client" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/logging" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum/go-ethereum/common" @@ -27,29 +27,29 @@ const withdrawalEnforceMsg = ` Transaction Hash: %s ` -// WithdrawalEnforceCfg ... Configuration for the balance invariant +// WithdrawalEnforceCfg ... Configuration for the balance heuristic type WithdrawalEnforceCfg struct { L1PortalAddress string `json:"l1_portal_address"` L2ToL1Address string `json:"l2_to_l1_address"` } -// WithdrawalEnforceInv ... WithdrawalEnforceInvariant implementation +// WithdrawalEnforceInv ... WithdrawalEnforceHeuristic implementation type WithdrawalEnforceInv struct { eventHash common.Hash cfg *WithdrawalEnforceCfg l2tol1MessagePasser *bindings.L2ToL1MessagePasserCaller l1PortalFilter *bindings.OptimismPortalFilterer - invariant.Invariant + heuristic.Heuristic } -// Unmarshal ... Converts a general config to a balance invariant config -func (cfg *WithdrawalEnforceCfg) Unmarshal(isp *core.InvSessionParams) error { +// Unmarshal ... Converts a general config to a balance heuristic config +func (cfg *WithdrawalEnforceCfg) Unmarshal(isp *core.SessionParams) error { return json.Unmarshal(isp.Bytes(), &cfg) } // NewWithdrawalEnforceInv ... Initializer -func NewWithdrawalEnforceInv(ctx context.Context, cfg *WithdrawalEnforceCfg) (invariant.Invariant, error) { +func NewWithdrawalEnforceInv(ctx context.Context, cfg *WithdrawalEnforceCfg) (heuristic.Heuristic, error) { l2Client, err := client.FromContext(ctx, core.Layer2) if err != nil { return nil, err @@ -81,14 +81,14 @@ func NewWithdrawalEnforceInv(ctx context.Context, cfg *WithdrawalEnforceCfg) (in l1PortalFilter: filter, l2tol1MessagePasser: l2MessagePasser, - Invariant: invariant.NewBaseInvariant(core.EventLog), + Heuristic: heuristic.NewBaseHeuristic(core.EventLog), }, nil } -// Invalidate ... Verifies than an L1 WithdrawalProven has a correlating hash +// Assess ... Verifies than an L1 WithdrawalProven has a correlating hash // to the withdrawal storage of the L2ToL1MessagePasser -func (wi *WithdrawalEnforceInv) Invalidate(td core.TransitData) (*core.Invalidation, bool, error) { - logging.NoContext().Debug("Checking invalidation for withdrawal enforcement invariant", +func (wi *WithdrawalEnforceInv) Assess(td core.TransitData) (*core.Activation, bool, error) { + logging.NoContext().Debug("Checking activation for withdrawal enforcement heuristic", zap.String("data", fmt.Sprintf("%v", td))) // 1. Validate and extract data input @@ -117,9 +117,9 @@ func (wi *WithdrawalEnforceInv) Invalidate(td core.TransitData) (*core.Invalidat return nil, false, err } - // 4. If the withdrawal does not exist, invalidate + // 4. If the withdrawal does not exist, activate if !exists { - return &core.Invalidation{ + return &core.Activation{ TimeStamp: time.Now(), Message: fmt.Sprintf(withdrawalEnforceMsg, wi.cfg.L1PortalAddress, wi.cfg.L2ToL1Address, wi.SUUID(), log.TxHash.Hex()), diff --git a/internal/engine/store.go b/internal/engine/store.go index a1090057..61e73889 100644 --- a/internal/engine/store.go +++ b/internal/engine/store.go @@ -4,34 +4,34 @@ import ( "fmt" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" ) // SessionStore ... type SessionStore interface { - AddInvSession(sUUID core.SUUID, pID core.PUUID, inv invariant.Invariant) error - GetInstanceByUUID(sUUID core.SUUID) (invariant.Invariant, error) - GetInstancesByUUIDs(sUUIDs []core.SUUID) ([]invariant.Invariant, error) + AddSession(sUUID core.SUUID, pID core.PUUID, h heuristic.Heuristic) error + GetInstanceByUUID(sUUID core.SUUID) (heuristic.Heuristic, error) + GetInstancesByUUIDs(sUUIDs []core.SUUID) ([]heuristic.Heuristic, error) GetSUUIDsByPUUID(pUUID core.PUUID) ([]core.SUUID, error) } // sessionStore ... type sessionStore struct { idMap map[core.PUUID][]core.SUUID - instanceMap map[core.SUUID]invariant.Invariant // no duplicates + instanceMap map[core.SUUID]heuristic.Heuristic // no duplicates } // NewSessionStore ... Initializer func NewSessionStore() SessionStore { return &sessionStore{ - instanceMap: make(map[core.SUUID]invariant.Invariant), + instanceMap: make(map[core.SUUID]heuristic.Heuristic), idMap: make(map[core.PUUID][]core.SUUID), } } -// GetInstancesByUUIDs ... Fetches in-order all invariants associated with a set of session UUIDs -func (ss *sessionStore) GetInstancesByUUIDs(sUUIDs []core.SUUID) ([]invariant.Invariant, error) { - invariants := make([]invariant.Invariant, len(sUUIDs)) +// GetInstancesByUUIDs ... Fetches in-order all heuristics associated with a set of session UUIDs +func (ss *sessionStore) GetInstancesByUUIDs(sUUIDs []core.SUUID) ([]heuristic.Heuristic, error) { + heuristics := make([]heuristic.Heuristic, len(sUUIDs)) for i, uuid := range sUUIDs { session, err := ss.GetInstanceByUUID(uuid) @@ -39,46 +39,46 @@ func (ss *sessionStore) GetInstancesByUUIDs(sUUIDs []core.SUUID) ([]invariant.In return nil, err } - invariants[i] = session + heuristics[i] = session } - return invariants, nil + return heuristics, nil } -// GetInstanceByUUID .... Fetches invariant session by SUUID -func (ss *sessionStore) GetInstanceByUUID(sUUID core.SUUID) (invariant.Invariant, error) { +// GetInstanceByUUID .... Fetches heuristic session by SUUID +func (ss *sessionStore) GetInstanceByUUID(sUUID core.SUUID) (heuristic.Heuristic, error) { if entry, found := ss.instanceMap[sUUID]; found { return entry, nil } - return nil, fmt.Errorf("invariant UUID doesn't exists in store inv mapping") + return nil, fmt.Errorf("heuristic UUID doesn't exists in store heuristic mapping") } -// GetSUUIDsByPUUID ... Returns all invariant session ids associated with pipeline +// GetSUUIDsByPUUID ... Returns all heuristic session ids associated with pipeline func (ss *sessionStore) GetSUUIDsByPUUID(pUUID core.PUUID) ([]core.SUUID, error) { if sessionIDs, found := ss.idMap[pUUID]; found { return sessionIDs, nil } - return nil, fmt.Errorf("pipeline UUID doesn't exists in store inv mapping") + return nil, fmt.Errorf("pipeline UUID doesn't exists in store heuristic mapping") } -// AddInvSession ... Adds an invariant session to the store -func (ss *sessionStore) AddInvSession(sUUID core.SUUID, - pUUID core.PUUID, inv invariant.Invariant) error { +// AddSession ... Adds an heuristic session to the store +func (ss *sessionStore) AddSession(sUUID core.SUUID, + pUUID core.PUUID, h heuristic.Heuristic) error { if _, found := ss.instanceMap[sUUID]; found { - return fmt.Errorf("invariant UUID already exists in store pid mapping") + return fmt.Errorf("heuristic UUID already exists in store pid mapping") } if _, found := ss.idMap[pUUID]; !found { ss.idMap[pUUID] = make([]core.SUUID, 0) } - ss.instanceMap[sUUID] = inv + ss.instanceMap[sUUID] = h ss.idMap[pUUID] = append(ss.idMap[pUUID], sUUID) return nil } -// RemoveInvSession ... Removes an existing invariant session from the store +// RemoveInvSession ... Removes an existing heuristic session from the store func (ss *sessionStore) RemoveInvSession(_ core.SUUID, - _ core.PUUID, _ invariant.Invariant) error { + _ core.PUUID, _ heuristic.Heuristic) error { return nil } diff --git a/internal/engine/store_test.go b/internal/engine/store_test.go index 5cfeeb12..c76abbaa 100644 --- a/internal/engine/store_test.go +++ b/internal/engine/store_test.go @@ -6,13 +6,13 @@ import ( "github.com/base-org/pessimism/internal/core" "github.com/base-org/pessimism/internal/engine" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/stretchr/testify/assert" ) func TestSessionStore(t *testing.T) { - sUUID1 := core.MakeSUUID(core.Layer1, core.Live, core.InvariantType(0)) - sUUID2 := core.MakeSUUID(core.Layer2, core.Live, core.InvariantType(0)) + sUUID1 := core.MakeSUUID(core.Layer1, core.Live, core.HeuristicType(0)) + sUUID2 := core.MakeSUUID(core.Layer2, core.Live, core.HeuristicType(0)) pUUID1 := core.NilPUUID() var tests = []struct { @@ -26,18 +26,18 @@ func TestSessionStore(t *testing.T) { constructor: func() engine.SessionStore { ss := engine.NewSessionStore() - inv := invariant.NewBaseInvariant(core.RegisterType(0)) - inv.SetSUUID(sUUID1) + h := heuristic.NewBaseHeuristic(core.RegisterType(0)) + h.SetSUUID(sUUID1) - _ = ss.AddInvSession(sUUID1, pUUID1, inv) + _ = ss.AddSession(sUUID1, pUUID1, h) return ss }, testFunc: func(t *testing.T, ss engine.SessionStore) { - // Ensure that the invariant is retrievable - inv, err := ss.GetInstanceByUUID(sUUID1) + // Ensure that the heuristic is retrievable + h, err := ss.GetInstanceByUUID(sUUID1) assert.NoError(t, err) - assert.Equal(t, inv.SUUID(), sUUID1) + assert.Equal(t, h.SUUID(), sUUID1) // Ensure that pipeline UUIDs are retrievable sUUIDs, err := ss.GetSUUIDsByPUUID(pUUID1) @@ -46,42 +46,42 @@ func TestSessionStore(t *testing.T) { }, }, { - name: "Successful Retrieval with Multiple Invariants", + name: "Successful Retrieval with Multiple Heuristics", constructor: func() engine.SessionStore { ss := engine.NewSessionStore() - inv := invariant.NewBaseInvariant(core.RegisterType(0)) - inv.SetSUUID(sUUID1) + h := heuristic.NewBaseHeuristic(core.RegisterType(0)) + h.SetSUUID(sUUID1) - _ = ss.AddInvSession(sUUID1, pUUID1, inv) + _ = ss.AddSession(sUUID1, pUUID1, h) - inv2 := invariant.NewBaseInvariant(core.RegisterType(0)) - inv2.SetSUUID(sUUID2) + h2 := heuristic.NewBaseHeuristic(core.RegisterType(0)) + h2.SetSUUID(sUUID2) - _ = ss.AddInvSession(sUUID2, pUUID1, inv2) + _ = ss.AddSession(sUUID2, pUUID1, h2) return ss }, testFunc: func(t *testing.T, ss engine.SessionStore) { - // Ensure that the first inserted invariant is retrievable - inv, err := ss.GetInstanceByUUID(sUUID1) + // Ensure that the first inserted heuristic is retrievable + h, err := ss.GetInstanceByUUID(sUUID1) assert.NoError(t, err) - assert.Equal(t, inv.SUUID(), sUUID1) + assert.Equal(t, h.SUUID(), sUUID1) - // Ensure that the second inserted invariant is retrievable - inv2, err := ss.GetInstanceByUUID(sUUID2) + // Ensure that the second inserted heuristic is retrievable + h2, err := ss.GetInstanceByUUID(sUUID2) assert.NoError(t, err) - assert.Equal(t, inv2.SUUID(), sUUID2) + assert.Equal(t, h2.SUUID(), sUUID2) // Ensure that pipeline UUIDs are retrievable sUUIDs, err := ss.GetSUUIDsByPUUID(pUUID1) assert.NoError(t, err) assert.Equal(t, sUUIDs, []core.SUUID{sUUID1, sUUID2}) - // Ensure that both invariants are retrievable at once - invs, err := ss.GetInstancesByUUIDs([]core.SUUID{sUUID1, sUUID2}) + // Ensure that both heuristics are retrievable at once + hs, err := ss.GetInstancesByUUIDs([]core.SUUID{sUUID1, sUUID2}) assert.NoError(t, err) - assert.Equal(t, invs, []invariant.Invariant{inv, inv2}) + assert.Equal(t, hs, []heuristic.Heuristic{h, h2}) }, }, { @@ -89,17 +89,17 @@ func TestSessionStore(t *testing.T) { constructor: func() engine.SessionStore { ss := engine.NewSessionStore() - inv := invariant.NewBaseInvariant(core.RegisterType(0)) - inv.SetSUUID(sUUID1) + h := heuristic.NewBaseHeuristic(core.RegisterType(0)) + h.SetSUUID(sUUID1) - _ = ss.AddInvSession(sUUID1, pUUID1, inv) + _ = ss.AddSession(sUUID1, pUUID1, h) return ss }, testFunc: func(t *testing.T, ss engine.SessionStore) { - // Ensure that the invariant is retrievable - inv, err := ss.GetInstanceByUUID(sUUID1) + // Ensure that the heuristic is retrievable + h, err := ss.GetInstanceByUUID(sUUID1) assert.NoError(t, err) - assert.Equal(t, inv.SUUID(), sUUID1) + assert.Equal(t, h.SUUID(), sUUID1) // Ensure that pipeline UUIDs are retrievable sUUIDs, err := ss.GetSUUIDsByPUUID(pUUID1) @@ -112,14 +112,14 @@ func TestSessionStore(t *testing.T) { constructor: func() engine.SessionStore { ss := engine.NewSessionStore() - inv := invariant.NewBaseInvariant(core.RegisterType(0)) - _ = ss.AddInvSession(sUUID1, pUUID1, inv) + h := heuristic.NewBaseHeuristic(core.RegisterType(0)) + _ = ss.AddSession(sUUID1, pUUID1, h) return ss }, testFunc: func(t *testing.T, ss engine.SessionStore) { - inv, err := ss.GetInstanceByUUID(sUUID2) - assert.Nil(t, inv) + h, err := ss.GetInstanceByUUID(sUUID2) + assert.Nil(t, h) assert.Error(t, err) }, }, @@ -128,14 +128,14 @@ func TestSessionStore(t *testing.T) { constructor: func() engine.SessionStore { ss := engine.NewSessionStore() - inv := invariant.NewBaseInvariant(core.RegisterType(0)) - _ = ss.AddInvSession(sUUID1, pUUID1, inv) + h := heuristic.NewBaseHeuristic(core.RegisterType(0)) + _ = ss.AddSession(sUUID1, pUUID1, h) return ss }, testFunc: func(t *testing.T, ss engine.SessionStore) { // Ensure that only one suuid can exist in the store - err := ss.AddInvSession(sUUID1, pUUID1, invariant.NewBaseInvariant(core.RegisterType(0))) + err := ss.AddSession(sUUID1, pUUID1, heuristic.NewBaseHeuristic(core.RegisterType(0))) assert.Error(t, err) }, }, diff --git a/internal/etl/component/egress_test.go b/internal/etl/component/egress_test.go index 069f1cba..97ff26a8 100644 --- a/internal/etl/component/egress_test.go +++ b/internal/etl/component/egress_test.go @@ -125,7 +125,7 @@ func Test_Add_Remove_Egress(t *testing.T) { constructionLogic: newEgressHandler, testLogic: func(t *testing.T, eh *egressHandler) { - relayChan := make(chan core.InvariantInput) + relayChan := make(chan core.HeuristicInput) pUUID := core.NilPUUID() @@ -137,7 +137,7 @@ func Test_Add_Remove_Egress(t *testing.T) { assert.NoError(t, err) testData := core.TransitData{Network: 2, Value: "goodbye closed-source blocksec monitoring"} - expectedInput := core.InvariantInput{ + expectedInput := core.HeuristicInput{ PUUID: pUUID, Input: testData, } @@ -157,7 +157,7 @@ func Test_Add_Remove_Egress(t *testing.T) { description: "When relay already exists and AddRelay function is called, an error should be returned", constructionLogic: func() *egressHandler { - relayChan := make(chan core.InvariantInput) + relayChan := make(chan core.HeuristicInput) pUUID := core.NilPUUID() @@ -173,7 +173,7 @@ func Test_Add_Remove_Egress(t *testing.T) { }, testLogic: func(t *testing.T, eh *egressHandler) { - relayChan := make(chan core.InvariantInput) + relayChan := make(chan core.HeuristicInput) pUUID := core.NilPUUID() diff --git a/internal/etl/component/types.go b/internal/etl/component/types.go index a2c32a28..d1b97133 100644 --- a/internal/etl/component/types.go +++ b/internal/etl/component/types.go @@ -67,8 +67,8 @@ type ( type OracleType = string const ( - // BackTestOracle ... Represents an oracle used for backtesting some invariant + // BackTestOracle ... Represents an oracle used for backtesting some heuristic BacktestOracle OracleType = "backtest" - // LiveOracle ... Represents an oracle used for powering some live invariant + // LiveOracle ... Represents an oracle used for powering some live heuristic LiveOracle OracleType = "live" ) diff --git a/internal/etl/pipeline/manager.go b/internal/etl/pipeline/manager.go index 4c953098..68692868 100644 --- a/internal/etl/pipeline/manager.go +++ b/internal/etl/pipeline/manager.go @@ -38,7 +38,7 @@ type etlManager struct { store EtlStore metrics metrics.Metricer - egress chan core.InvariantInput + egress chan core.HeuristicInput registry registry.Registry wg sync.WaitGroup @@ -47,7 +47,7 @@ type etlManager struct { // NewManager ... Initializer func NewManager(ctx context.Context, analyzer Analyzer, cRegistry registry.Registry, store EtlStore, dag ComponentGraph, - eo chan core.InvariantInput) Manager { + eo chan core.HeuristicInput) Manager { ctx, cancel := context.WithCancel(ctx) stats := metrics.WithContext(ctx) @@ -209,7 +209,7 @@ func (em *etlManager) getMergeUUID(pUUID core.PUUID, pipeline Pipeline) (core.PU return core.NilPUUID(), err } - if em.analyzer.Mergable(pipeline, p) { // Deploy invariants to existing pipelines instead + if em.analyzer.Mergable(pipeline, p) { // Deploy heuristics to existing pipelines instead // This is a bit hacky since we aren't actually merging the pipelines return p.UUID(), nil } diff --git a/internal/etl/pipeline/pipeline.go b/internal/etl/pipeline/pipeline.go index 05551de0..4437357f 100644 --- a/internal/etl/pipeline/pipeline.go +++ b/internal/etl/pipeline/pipeline.go @@ -19,7 +19,7 @@ type Pipeline interface { Close() error Run(wg *sync.WaitGroup) - AddEngineRelay(engineChan chan core.InvariantInput) error + AddEngineRelay(engineChan chan core.HeuristicInput) error } // pipeline ... Pipeline implementation @@ -68,9 +68,9 @@ func (pl *pipeline) UUID() core.PUUID { return pl.id } -// AddEngineRelay ... Adds a relay to the pipeline that forces it to send transformed invariant input +// AddEngineRelay ... Adds a relay to the pipeline that forces it to send transformed heuristic input // to a risk engine -func (pl *pipeline) AddEngineRelay(engineChan chan core.InvariantInput) error { +func (pl *pipeline) AddEngineRelay(engineChan chan core.HeuristicInput) error { lastComponent := pl.components[0] eir := core.NewEngineRelay(pl.id, engineChan) diff --git a/internal/etl/pipeline/pipeline_test.go b/internal/etl/pipeline/pipeline_test.go index 52ffaf20..bcc0e22c 100644 --- a/internal/etl/pipeline/pipeline_test.go +++ b/internal/etl/pipeline/pipeline_test.go @@ -73,7 +73,7 @@ func Test_Pipeline(t *testing.T) { }, testLogic: func(t *testing.T, pl pipeline.Pipeline) { - relay := make(chan core.InvariantInput) + relay := make(chan core.HeuristicInput) err := pl.AddEngineRelay(relay) assert.NoError(t, err) }, diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index f1060064..a4304dcf 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -6,7 +6,7 @@ import ( "time" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/logging" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" @@ -16,7 +16,7 @@ import ( const ( metricsNamespace = "pessimism" - SubsystemInvariants = "invariants" + SubsystemHeuristics = "heuristics" SubsystemEtl = "etl" ) @@ -30,16 +30,16 @@ type Config struct { } type Metricer interface { - IncActiveInvariants(invType core.InvariantType, network core.Network, pipelineType core.PipelineType) + IncActiveHeuristics(ht core.HeuristicType, network core.Network, pipelineType core.PipelineType) IncActivePipelines(pipelineType core.PipelineType, network core.Network) DecActivePipelines(pipelineType core.PipelineType, network core.Network) RecordBlockLatency(network core.Network, latency float64) - RecordInvariantRun(invariant invariant.Invariant) + RecordHeuristicRun(heuristic heuristic.Heuristic) RecordAlertGenerated(alert core.Alert) RecordNodeError(network core.Network) RecordPipelineLatency(pUUID core.PUUID, latency float64) - RecordInvExecutionError(inv invariant.Invariant) - RecordInvExecutionTime(inv invariant.Invariant, latency float64) + RecordAssessmentError(h heuristic.Heuristic) + RecordInvExecutionTime(h heuristic.Heuristic, latency float64) RecordUp() Start() Shutdown(ctx context.Context) error @@ -49,14 +49,14 @@ type Metricer interface { type Metrics struct { Up prometheus.Gauge ActivePipelines *prometheus.GaugeVec - ActiveInvariants *prometheus.GaugeVec - InvariantRuns *prometheus.CounterVec + ActiveHeuristics *prometheus.GaugeVec + HeuristicRuns *prometheus.CounterVec AlertsGenerated *prometheus.CounterVec NodeErrors *prometheus.CounterVec BlockLatency *prometheus.GaugeVec PipelineLatency *prometheus.GaugeVec InvExecutionTime *prometheus.GaugeVec - InvariantErrors *prometheus.CounterVec + HeuristicErrors *prometheus.CounterVec registry *prometheus.Registry factory Factory @@ -92,12 +92,12 @@ func New(ctx context.Context, cfg *Config) (Metricer, func(), error) { Name: "up", Help: "1 if the service is up", }), - ActiveInvariants: factory.NewGaugeVec(prometheus.GaugeOpts{ - Name: "active_invariants", - Help: "Number of active invariants", + ActiveHeuristics: factory.NewGaugeVec(prometheus.GaugeOpts{ + Name: "active_heuristics", + Help: "Number of active heuristics", Namespace: metricsNamespace, - Subsystem: SubsystemInvariants, - }, []string{"invariant", "network", "pipeline"}), + Subsystem: SubsystemHeuristics, + }, []string{"heuristic", "network", "pipeline"}), ActivePipelines: factory.NewGaugeVec(prometheus.GaugeOpts{ Name: "active_pipelines", @@ -106,18 +106,18 @@ func New(ctx context.Context, cfg *Config) (Metricer, func(), error) { Subsystem: SubsystemEtl, }, []string{"pipeline", "network"}), - InvariantRuns: factory.NewCounterVec(prometheus.CounterOpts{ - Name: "invariant_runs_total", - Help: "Number of times a specific invariant has been run", + HeuristicRuns: factory.NewCounterVec(prometheus.CounterOpts{ + Name: "heuristic_runs_total", + Help: "Number of times a specific heuristic has been run", Namespace: metricsNamespace, - Subsystem: SubsystemInvariants, - }, []string{"network", "invariant"}), + Subsystem: SubsystemHeuristics, + }, []string{"network", "heuristic"}), AlertsGenerated: factory.NewCounterVec(prometheus.CounterOpts{ Name: "alerts_generated_total", - Help: "Number of total alerts generated for a given invariant", + Help: "Number of total alerts generated for a given heuristic", Namespace: metricsNamespace, - }, []string{"network", "invariant", "pipeline", "destination"}), + }, []string{"network", "heuristic", "pipeline", "destination"}), NodeErrors: factory.NewCounterVec(prometheus.CounterOpts{ Name: "node_errors_total", @@ -136,15 +136,15 @@ func New(ctx context.Context, cfg *Config) (Metricer, func(), error) { Namespace: metricsNamespace, }, []string{"puuid"}), InvExecutionTime: factory.NewGaugeVec(prometheus.GaugeOpts{ - Name: "invariant_execution_time", - Help: "Nanosecond time of invariant execution", + Name: "heuristic_execution_time", + Help: "Nanosecond time of heuristic execution", Namespace: metricsNamespace, - }, []string{"invariant"}), - InvariantErrors: factory.NewCounterVec(prometheus.CounterOpts{ - Name: "invariant_errors_total", - Help: "Number of errors generated by invariant executions", + }, []string{"heuristic"}), + HeuristicErrors: factory.NewCounterVec(prometheus.CounterOpts{ + Name: "heuristic_errors_total", + Help: "Number of errors generated by heuristic executions", Namespace: metricsNamespace, - }, []string{"invariant"}), + }, []string{"heuristic"}), registry: registry, factory: factory, @@ -170,58 +170,58 @@ func (m *Metrics) RecordUp() { m.Up.Set(1) } -// RecordInvExecutionError ... Increments the number of errors generated by invariant executions -func (m *Metrics) RecordInvExecutionError(inv invariant.Invariant) { - invType := inv.SUUID().PID.InvType().String() - m.InvariantErrors.WithLabelValues(invType).Inc() +// RecordAssessmentError ... Increments the number of errors generated by heuristic executions +func (m *Metrics) RecordAssessmentError(h heuristic.Heuristic) { + ht := h.SUUID().PID.HeuristicType().String() + m.HeuristicErrors.WithLabelValues(ht).Inc() } -// RecordInvExecutionTime ... Records the time it took to execute an invariant -func (m *Metrics) RecordInvExecutionTime(inv invariant.Invariant, latency float64) { - invType := inv.SUUID().PID.InvType().String() - m.InvExecutionTime.WithLabelValues(invType).Set(latency) +// RecordInvExecutionTime ... Records the time it took to execute an heuristic +func (m *Metrics) RecordInvExecutionTime(h heuristic.Heuristic, latency float64) { + ht := h.SUUID().PID.HeuristicType().String() + m.InvExecutionTime.WithLabelValues(ht).Set(latency) } -// IncActiveInvariants ... Increments the number of active invariants -func (m *Metrics) IncActiveInvariants(invType core.InvariantType, network core.Network, +// IncActiveHeuristics ... Increments the number of active heuristics +func (m *Metrics) IncActiveHeuristics(ht core.HeuristicType, n core.Network, pipelineType core.PipelineType) { - m.ActiveInvariants.WithLabelValues(invType.String(), network.String(), pipelineType.String()).Inc() + m.ActiveHeuristics.WithLabelValues(ht.String(), n.String(), pipelineType.String()).Inc() } // IncActivePipelines ... Increments the number of active pipelines -func (m *Metrics) IncActivePipelines(pipelineType core.PipelineType, network core.Network) { - m.ActivePipelines.WithLabelValues(pipelineType.String(), network.String()).Inc() +func (m *Metrics) IncActivePipelines(pt core.PipelineType, n core.Network) { + m.ActivePipelines.WithLabelValues(pt.String(), n.String()).Inc() } // DecActivePipelines ... Decrements the number of active pipelines -func (m *Metrics) DecActivePipelines(pipelineType core.PipelineType, network core.Network) { - m.ActivePipelines.WithLabelValues(pipelineType.String(), network.String()).Dec() +func (m *Metrics) DecActivePipelines(pt core.PipelineType, n core.Network) { + m.ActivePipelines.WithLabelValues(pt.String(), n.String()).Dec() } -// RecordInvariantRun ... Records that a given invariant has been run -func (m *Metrics) RecordInvariantRun(inv invariant.Invariant) { - net := inv.SUUID().PID.Network().String() - invType := inv.SUUID().PID.InvType().String() - m.InvariantRuns.WithLabelValues(net, invType).Inc() +// RecordHeuristicRun ... Records that a given heuristic has been run +func (m *Metrics) RecordHeuristicRun(h heuristic.Heuristic) { + net := h.SUUID().PID.Network().String() + ht := h.SUUID().PID.HeuristicType().String() + m.HeuristicRuns.WithLabelValues(net, ht).Inc() } -// RecordAlertGenerated ... Records that an alert has been generated for a given invariant +// RecordAlertGenerated ... Records that an alert has been generated for a given heuristic func (m *Metrics) RecordAlertGenerated(alert core.Alert) { net := alert.SUUID.PID.Network().String() - inv := alert.SUUID.PID.InvType().String() + h := alert.SUUID.PID.HeuristicType().String() pipeline := alert.Ptype.String() dest := alert.Dest.String() - m.AlertsGenerated.WithLabelValues(net, inv, pipeline, dest).Inc() + m.AlertsGenerated.WithLabelValues(net, h, pipeline, dest).Inc() } // RecordNodeError ... Records that an error has been caught for a given node -func (m *Metrics) RecordNodeError(network core.Network) { - m.NodeErrors.WithLabelValues(network.String()).Inc() +func (m *Metrics) RecordNodeError(n core.Network) { + m.NodeErrors.WithLabelValues(n.String()).Inc() } // RecordBlockLatency ... Records the latency of block processing -func (m *Metrics) RecordBlockLatency(network core.Network, latency float64) { - m.BlockLatency.WithLabelValues(network.String()).Set(latency) +func (m *Metrics) RecordBlockLatency(n core.Network, latency float64) { + m.BlockLatency.WithLabelValues(n.String()).Set(latency) } // RecordPipelineLatency ... Records the latency of pipeline processing @@ -244,17 +244,17 @@ type noopMetricer struct{} var NoopMetrics Metricer = new(noopMetricer) func (n *noopMetricer) RecordUp() {} -func (n *noopMetricer) IncActiveInvariants(_ core.InvariantType, _ core.Network, _ core.PipelineType) { +func (n *noopMetricer) IncActiveHeuristics(_ core.HeuristicType, _ core.Network, _ core.PipelineType) { } -func (n *noopMetricer) RecordInvExecutionTime(_ invariant.Invariant, _ float64) {} +func (n *noopMetricer) RecordInvExecutionTime(_ heuristic.Heuristic, _ float64) {} func (n *noopMetricer) IncActivePipelines(_ core.PipelineType, _ core.Network) {} func (n *noopMetricer) DecActivePipelines(_ core.PipelineType, _ core.Network) {} -func (n *noopMetricer) RecordInvariantRun(_ invariant.Invariant) {} +func (n *noopMetricer) RecordHeuristicRun(_ heuristic.Heuristic) {} func (n *noopMetricer) RecordAlertGenerated(_ core.Alert) {} func (n *noopMetricer) RecordNodeError(_ core.Network) {} func (n *noopMetricer) RecordBlockLatency(_ core.Network, _ float64) {} func (n *noopMetricer) RecordPipelineLatency(_ core.PUUID, _ float64) {} -func (n *noopMetricer) RecordInvExecutionError(_ invariant.Invariant) {} +func (n *noopMetricer) RecordAssessmentError(_ heuristic.Heuristic) {} func (n *noopMetricer) Shutdown(_ context.Context) error { return nil diff --git a/internal/mocks/api_service.go b/internal/mocks/api_service.go index c06d45d1..c7edc8d3 100644 --- a/internal/mocks/api_service.go +++ b/internal/mocks/api_service.go @@ -63,32 +63,32 @@ func (mr *MockServiceMockRecorder) CheckHealth() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckHealth", reflect.TypeOf((*MockService)(nil).CheckHealth)) } -// ProcessInvariantRequest mocks base method. -func (m *MockService) ProcessInvariantRequest(arg0 *models.InvRequestBody) (core.SUUID, error) { +// ProcessHeuristicRequest mocks base method. +func (m *MockService) ProcessHeuristicRequest(arg0 *models.SessionRequestBody) (core.SUUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ProcessInvariantRequest", arg0) + ret := m.ctrl.Call(m, "ProcessHeuristicRequest", arg0) ret0, _ := ret[0].(core.SUUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// ProcessInvariantRequest indicates an expected call of ProcessInvariantRequest. -func (mr *MockServiceMockRecorder) ProcessInvariantRequest(arg0 interface{}) *gomock.Call { +// ProcessHeuristicRequest indicates an expected call of ProcessHeuristicRequest. +func (mr *MockServiceMockRecorder) ProcessHeuristicRequest(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessInvariantRequest", reflect.TypeOf((*MockService)(nil).ProcessInvariantRequest), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessHeuristicRequest", reflect.TypeOf((*MockService)(nil).ProcessHeuristicRequest), arg0) } -// RunInvariantSession mocks base method. -func (m *MockService) RunInvariantSession(arg0 *models.InvRequestParams) (core.SUUID, error) { +// RunHeuristicSession mocks base method. +func (m *MockService) RunHeuristicSession(arg0 *models.SessionRequestParams) (core.SUUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RunInvariantSession", arg0) + ret := m.ctrl.Call(m, "RunHeuristicSession", arg0) ret0, _ := ret[0].(core.SUUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// RunInvariantSession indicates an expected call of RunInvariantSession. -func (mr *MockServiceMockRecorder) RunInvariantSession(arg0 interface{}) *gomock.Call { +// RunHeuristicSession indicates an expected call of RunHeuristicSession. +func (mr *MockServiceMockRecorder) RunHeuristicSession(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunInvariantSession", reflect.TypeOf((*MockService)(nil).RunInvariantSession), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunHeuristicSession", reflect.TypeOf((*MockService)(nil).RunHeuristicSession), arg0) } diff --git a/internal/mocks/engine_manager.go b/internal/mocks/engine_manager.go index 48c5c8f2..3debe1b9 100644 --- a/internal/mocks/engine_manager.go +++ b/internal/mocks/engine_manager.go @@ -8,7 +8,7 @@ import ( reflect "reflect" core "github.com/base-org/pessimism/internal/core" - invariant "github.com/base-org/pessimism/internal/engine/invariant" + heuristic "github.com/base-org/pessimism/internal/engine/heuristic" gomock "github.com/golang/mock/gomock" ) @@ -35,34 +35,34 @@ func (m *EngineManager) EXPECT() *EngineManagerMockRecorder { return m.recorder } -// DeleteInvariantSession mocks base method. -func (m *EngineManager) DeleteInvariantSession(arg0 core.SUUID) (core.SUUID, error) { +// DeleteHeuristicSession mocks base method. +func (m *EngineManager) DeleteHeuristicSession(arg0 core.SUUID) (core.SUUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteInvariantSession", arg0) + ret := m.ctrl.Call(m, "DeleteHeuristicSession", arg0) ret0, _ := ret[0].(core.SUUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// DeleteInvariantSession indicates an expected call of DeleteInvariantSession. -func (mr *EngineManagerMockRecorder) DeleteInvariantSession(arg0 interface{}) *gomock.Call { +// DeleteHeuristicSession indicates an expected call of DeleteHeuristicSession. +func (mr *EngineManagerMockRecorder) DeleteHeuristicSession(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteInvariantSession", reflect.TypeOf((*EngineManager)(nil).DeleteInvariantSession), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteHeuristicSession", reflect.TypeOf((*EngineManager)(nil).DeleteHeuristicSession), arg0) } -// DeployInvariantSession mocks base method. -func (m *EngineManager) DeployInvariantSession(arg0 *invariant.DeployConfig) (core.SUUID, error) { +// DeployHeuristicSession mocks base method. +func (m *EngineManager) DeployHeuristicSession(arg0 *heuristic.DeployConfig) (core.SUUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeployInvariantSession", arg0) + ret := m.ctrl.Call(m, "DeployHeuristicSession", arg0) ret0, _ := ret[0].(core.SUUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// DeployInvariantSession indicates an expected call of DeployInvariantSession. -func (mr *EngineManagerMockRecorder) DeployInvariantSession(arg0 interface{}) *gomock.Call { +// DeployHeuristicSession indicates an expected call of DeployHeuristicSession. +func (mr *EngineManagerMockRecorder) DeployHeuristicSession(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeployInvariantSession", reflect.TypeOf((*EngineManager)(nil).DeployInvariantSession), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeployHeuristicSession", reflect.TypeOf((*EngineManager)(nil).DeployHeuristicSession), arg0) } // EventLoop mocks base method. @@ -80,7 +80,7 @@ func (mr *EngineManagerMockRecorder) EventLoop() *gomock.Call { } // GetInputType mocks base method. -func (m *EngineManager) GetInputType(arg0 core.InvariantType) (core.RegisterType, error) { +func (m *EngineManager) GetInputType(arg0 core.HeuristicType) (core.RegisterType, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetInputType", arg0) ret0, _ := ret[0].(core.RegisterType) @@ -109,10 +109,10 @@ func (mr *EngineManagerMockRecorder) Shutdown() *gomock.Call { } // Transit mocks base method. -func (m *EngineManager) Transit() chan core.InvariantInput { +func (m *EngineManager) Transit() chan core.HeuristicInput { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Transit") - ret0, _ := ret[0].(chan core.InvariantInput) + ret0, _ := ret[0].(chan core.HeuristicInput) return ret0 } diff --git a/internal/mocks/heuristic.go b/internal/mocks/heuristic.go new file mode 100644 index 00000000..19df3b3e --- /dev/null +++ b/internal/mocks/heuristic.go @@ -0,0 +1,105 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/base-org/pessimism/internal/engine/heuristic (interfaces: Heuristic) + +// Package mocks is a generated GoMock package. +package mocks + +import ( + reflect "reflect" + + core "github.com/base-org/pessimism/internal/core" + gomock "github.com/golang/mock/gomock" +) + +// MockHeuristic is a mock of Heuristic interface. +type MockHeuristic struct { + ctrl *gomock.Controller + recorder *MockHeuristicMockRecorder +} + +// MockHeuristicMockRecorder is the mock recorder for MockHeuristic. +type MockHeuristicMockRecorder struct { + mock *MockHeuristic +} + +// NewMockHeuristic creates a new mock instance. +func NewMockHeuristic(ctrl *gomock.Controller) *MockHeuristic { + mock := &MockHeuristic{ctrl: ctrl} + mock.recorder = &MockHeuristicMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHeuristic) EXPECT() *MockHeuristicMockRecorder { + return m.recorder +} + +// Assess mocks base method. +func (m *MockHeuristic) Assess(arg0 core.TransitData) (*core.Activation, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Assess", arg0) + ret0, _ := ret[0].(*core.Activation) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// Assess indicates an expected call of Assess. +func (mr *MockHeuristicMockRecorder) Assess(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Assess", reflect.TypeOf((*MockHeuristic)(nil).Assess), arg0) +} + +// InputType mocks base method. +func (m *MockHeuristic) InputType() core.RegisterType { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InputType") + ret0, _ := ret[0].(core.RegisterType) + return ret0 +} + +// InputType indicates an expected call of InputType. +func (mr *MockHeuristicMockRecorder) InputType() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InputType", reflect.TypeOf((*MockHeuristic)(nil).InputType)) +} + +// SUUID mocks base method. +func (m *MockHeuristic) SUUID() core.SUUID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SUUID") + ret0, _ := ret[0].(core.SUUID) + return ret0 +} + +// SUUID indicates an expected call of SUUID. +func (mr *MockHeuristicMockRecorder) SUUID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SUUID", reflect.TypeOf((*MockHeuristic)(nil).SUUID)) +} + +// SetSUUID mocks base method. +func (m *MockHeuristic) SetSUUID(arg0 core.SUUID) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetSUUID", arg0) +} + +// SetSUUID indicates an expected call of SetSUUID. +func (mr *MockHeuristicMockRecorder) SetSUUID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSUUID", reflect.TypeOf((*MockHeuristic)(nil).SetSUUID), arg0) +} + +// ValidateInput mocks base method. +func (m *MockHeuristic) ValidateInput(arg0 core.TransitData) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateInput", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateInput indicates an expected call of ValidateInput. +func (mr *MockHeuristicMockRecorder) ValidateInput(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateInput", reflect.TypeOf((*MockHeuristic)(nil).ValidateInput), arg0) +} diff --git a/internal/mocks/invariant.go b/internal/mocks/invariant.go deleted file mode 100644 index d18889d2..00000000 --- a/internal/mocks/invariant.go +++ /dev/null @@ -1,105 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/base-org/pessimism/internal/engine/invariant (interfaces: Invariant) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - core "github.com/base-org/pessimism/internal/core" - gomock "github.com/golang/mock/gomock" -) - -// MockInvariant is a mock of Invariant interface. -type MockInvariant struct { - ctrl *gomock.Controller - recorder *MockInvariantMockRecorder -} - -// MockInvariantMockRecorder is the mock recorder for MockInvariant. -type MockInvariantMockRecorder struct { - mock *MockInvariant -} - -// NewMockInvariant creates a new mock instance. -func NewMockInvariant(ctrl *gomock.Controller) *MockInvariant { - mock := &MockInvariant{ctrl: ctrl} - mock.recorder = &MockInvariantMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockInvariant) EXPECT() *MockInvariantMockRecorder { - return m.recorder -} - -// InputType mocks base method. -func (m *MockInvariant) InputType() core.RegisterType { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InputType") - ret0, _ := ret[0].(core.RegisterType) - return ret0 -} - -// InputType indicates an expected call of InputType. -func (mr *MockInvariantMockRecorder) InputType() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InputType", reflect.TypeOf((*MockInvariant)(nil).InputType)) -} - -// Invalidate mocks base method. -func (m *MockInvariant) Invalidate(arg0 core.TransitData) (*core.Invalidation, bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Invalidate", arg0) - ret0, _ := ret[0].(*core.Invalidation) - ret1, _ := ret[1].(bool) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// Invalidate indicates an expected call of Invalidate. -func (mr *MockInvariantMockRecorder) Invalidate(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Invalidate", reflect.TypeOf((*MockInvariant)(nil).Invalidate), arg0) -} - -// SUUID mocks base method. -func (m *MockInvariant) SUUID() core.SUUID { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SUUID") - ret0, _ := ret[0].(core.SUUID) - return ret0 -} - -// SUUID indicates an expected call of SUUID. -func (mr *MockInvariantMockRecorder) SUUID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SUUID", reflect.TypeOf((*MockInvariant)(nil).SUUID)) -} - -// SetSUUID mocks base method. -func (m *MockInvariant) SetSUUID(arg0 core.SUUID) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetSUUID", arg0) -} - -// SetSUUID indicates an expected call of SetSUUID. -func (mr *MockInvariantMockRecorder) SetSUUID(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSUUID", reflect.TypeOf((*MockInvariant)(nil).SetSUUID), arg0) -} - -// ValidateInput mocks base method. -func (m *MockInvariant) ValidateInput(arg0 core.TransitData) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ValidateInput", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// ValidateInput indicates an expected call of ValidateInput. -func (mr *MockInvariantMockRecorder) ValidateInput(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateInput", reflect.TypeOf((*MockInvariant)(nil).ValidateInput), arg0) -} diff --git a/internal/mocks/subsystem.go b/internal/mocks/subsystem.go index c7b3297d..9b442a2f 100644 --- a/internal/mocks/subsystem.go +++ b/internal/mocks/subsystem.go @@ -10,7 +10,7 @@ import ( models "github.com/base-org/pessimism/internal/api/models" core "github.com/base-org/pessimism/internal/core" - invariant "github.com/base-org/pessimism/internal/engine/invariant" + heuristic "github.com/base-org/pessimism/internal/engine/heuristic" gomock "github.com/golang/mock/gomock" ) @@ -38,10 +38,10 @@ func (m *SubManager) EXPECT() *SubManagerMockRecorder { } // BuildDeployCfg mocks base method. -func (m *SubManager) BuildDeployCfg(arg0 *core.PipelineConfig, arg1 *core.SessionConfig) (*invariant.DeployConfig, error) { +func (m *SubManager) BuildDeployCfg(arg0 *core.PipelineConfig, arg1 *core.SessionConfig) (*heuristic.DeployConfig, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BuildDeployCfg", arg0, arg1) - ret0, _ := ret[0].(*invariant.DeployConfig) + ret0, _ := ret[0].(*heuristic.DeployConfig) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -53,7 +53,7 @@ func (mr *SubManagerMockRecorder) BuildDeployCfg(arg0, arg1 interface{}) *gomock } // BuildPipelineCfg mocks base method. -func (m *SubManager) BuildPipelineCfg(arg0 *models.InvRequestParams) (*core.PipelineConfig, error) { +func (m *SubManager) BuildPipelineCfg(arg0 *models.SessionRequestParams) (*core.PipelineConfig, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BuildPipelineCfg", arg0) ret0, _ := ret[0].(*core.PipelineConfig) @@ -67,19 +67,19 @@ func (mr *SubManagerMockRecorder) BuildPipelineCfg(arg0 interface{}) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildPipelineCfg", reflect.TypeOf((*SubManager)(nil).BuildPipelineCfg), arg0) } -// RunInvSession mocks base method. -func (m *SubManager) RunInvSession(arg0 *invariant.DeployConfig) (core.SUUID, error) { +// RunSession mocks base method. +func (m *SubManager) RunSession(arg0 *heuristic.DeployConfig) (core.SUUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RunInvSession", arg0) + ret := m.ctrl.Call(m, "RunSession", arg0) ret0, _ := ret[0].(core.SUUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// RunInvSession indicates an expected call of RunInvSession. -func (mr *SubManagerMockRecorder) RunInvSession(arg0 interface{}) *gomock.Call { +// RunSession indicates an expected call of RunSession. +func (mr *SubManagerMockRecorder) RunSession(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunInvSession", reflect.TypeOf((*SubManager)(nil).RunInvSession), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunSession", reflect.TypeOf((*SubManager)(nil).RunSession), arg0) } // Shutdown mocks base method. diff --git a/internal/state/accessor.go b/internal/state/accessor.go index 896ec3a2..ceccbf8d 100644 --- a/internal/state/accessor.go +++ b/internal/state/accessor.go @@ -23,7 +23,7 @@ func InsertUnique(ctx context.Context, sk *core.StateKey, value string) error { } if err != nil { - logging.WithContext(ctx).Warn("Invariant session already exists in state store") + logging.WithContext(ctx).Warn("Heuristic session already exists in state store") } return nil } diff --git a/internal/subsystem/manager.go b/internal/subsystem/manager.go index 2eed71f4..7f90f106 100644 --- a/internal/subsystem/manager.go +++ b/internal/subsystem/manager.go @@ -12,7 +12,7 @@ import ( "github.com/base-org/pessimism/internal/api/models" "github.com/base-org/pessimism/internal/core" "github.com/base-org/pessimism/internal/engine" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/etl/pipeline" "github.com/base-org/pessimism/internal/logging" "github.com/base-org/pessimism/internal/metrics" @@ -42,9 +42,9 @@ func (cfg *Config) GetPollInterval(n core.Network) (time.Duration, error) { // Manager ... Subsystem manager interface type Manager interface { - BuildDeployCfg(pConfig *core.PipelineConfig, sConfig *core.SessionConfig) (*invariant.DeployConfig, error) - BuildPipelineCfg(params *models.InvRequestParams) (*core.PipelineConfig, error) - RunInvSession(cfg *invariant.DeployConfig) (core.SUUID, error) + BuildDeployCfg(pConfig *core.PipelineConfig, sConfig *core.SessionConfig) (*heuristic.DeployConfig, error) + BuildPipelineCfg(params *models.SessionRequestParams) (*core.PipelineConfig, error) + RunSession(cfg *heuristic.DeployConfig) (core.SUUID, error) // Orchestration StartEventRoutines(ctx context.Context) Shutdown() error @@ -128,7 +128,7 @@ func (m *manager) StartEventRoutines(ctx context.Context) { // BuildDeployCfg ... Builds a deploy config provided a pipeline & session config func (m *manager) BuildDeployCfg(pConfig *core.PipelineConfig, - sConfig *core.SessionConfig) (*invariant.DeployConfig, error) { + sConfig *core.SessionConfig) (*heuristic.DeployConfig, error) { // 1. Fetch state key using risk engine input register type sk, stateful, err := m.etl.GetStateKey(pConfig.DataType) if err != nil { @@ -145,33 +145,33 @@ func (m *manager) BuildDeployCfg(pConfig *core.PipelineConfig, Info("Created etl pipeline", zap.String(logging.PUUIDKey, pUUID.String())) // 3. Create a deploy config - return &invariant.DeployConfig{ - PUUID: pUUID, - Reuse: reuse, - InvType: sConfig.Type, - InvParams: sConfig.Params, - Network: pConfig.Network, - Stateful: stateful, - StateKey: sk, - AlertDest: sConfig.AlertDest, + return &heuristic.DeployConfig{ + PUUID: pUUID, + Reuse: reuse, + HeuristicType: sConfig.Type, + Params: sConfig.Params, + Network: pConfig.Network, + Stateful: stateful, + StateKey: sk, + AlertDest: sConfig.AlertDest, }, nil } -// RunInvSession ... Runs an invariant session -func (m *manager) RunInvSession(cfg *invariant.DeployConfig) (core.SUUID, error) { +// RunSession ... Runs an heuristic session +func (m *manager) RunSession(cfg *heuristic.DeployConfig) (core.SUUID, error) { // 1. Verify that pipeline constraints are met // NOTE - Consider introducing a config validation step or module if !cfg.Reuse && m.etlLimitReached() { return core.NilSUUID(), fmt.Errorf(maxPipelineErr, m.cfg.MaxPipelineCount) } - // 2. Deploy invariant session to risk engine - sUUID, err := m.eng.DeployInvariantSession(cfg) + // 2. Deploy heuristic session to risk engine + sUUID, err := m.eng.DeployHeuristicSession(cfg) if err != nil { return core.NilSUUID(), err } logging.WithContext(m.ctx). - Info("Deployed invariant session to risk engine", zap.String(logging.SUUIDKey, sUUID.String())) + Info("Deployed heuristic session to risk engine", zap.String(logging.SUUIDKey, sUUID.String())) // 3. Add session to alert manager err = m.alert.AddSession(sUUID, cfg.AlertDest) @@ -191,9 +191,9 @@ func (m *manager) RunInvSession(cfg *invariant.DeployConfig) (core.SUUID, error) return sUUID, nil } -// BuildPipelineCfg ... Builds a pipeline config provided a set of invariant request params -func (m *manager) BuildPipelineCfg(params *models.InvRequestParams) (*core.PipelineConfig, error) { - inType, err := m.eng.GetInputType(params.InvariantType()) +// BuildPipelineCfg ... Builds a pipeline config provided a set of heuristic request params +func (m *manager) BuildPipelineCfg(params *models.SessionRequestParams) (*core.PipelineConfig, error) { + inType, err := m.eng.GetInputType(params.Heuristic()) if err != nil { return nil, err } diff --git a/internal/subsystem/manager_test.go b/internal/subsystem/manager_test.go index b6815078..9dfb5124 100644 --- a/internal/subsystem/manager_test.go +++ b/internal/subsystem/manager_test.go @@ -7,7 +7,7 @@ import ( "github.com/base-org/pessimism/internal/api/models" "github.com/base-org/pessimism/internal/core" - "github.com/base-org/pessimism/internal/engine/invariant" + "github.com/base-org/pessimism/internal/engine/heuristic" "github.com/base-org/pessimism/internal/mocks" "github.com/base-org/pessimism/internal/subsystem" "github.com/golang/mock/gomock" @@ -116,18 +116,18 @@ func Test_BuildDeployCfg(t *testing.T) { } } -func Test_RunInvSession(t *testing.T) { +func Test_RunSession(t *testing.T) { testSUUID := core.MakeSUUID(1, 1, 1) - testCfg := &invariant.DeployConfig{ + testCfg := &heuristic.DeployConfig{ Stateful: false, StateKey: nil, Network: core.Layer1, PUUID: core.NilPUUID(), Reuse: false, - InvType: core.BalanceEnforcement, - InvParams: nil, - AlertDest: core.Slack, + HeuristicType: core.BalanceEnforcement, + Params: nil, + AlertDest: core.Slack, } var tests = []struct { @@ -136,34 +136,34 @@ func Test_RunInvSession(t *testing.T) { testLogic func(t *testing.T, ts *testSuite) }{ { - name: "Failure when deploying invariant session", + name: "Failure when deploying heuristic session", constructor: func(t *testing.T) *testSuite { ts := createTestSuite(t) ts.mockEtl.EXPECT(). ActiveCount().Return(1). Times(1) - ts.mockEng.EXPECT().DeployInvariantSession(testCfg). + ts.mockEng.EXPECT().DeployHeuristicSession(testCfg). Return(core.NilSUUID(), testErr()). Times(1) return ts }, testLogic: func(t *testing.T, ts *testSuite) { - actualSUUID, err := ts.subsys.RunInvSession(testCfg) + actualSUUID, err := ts.subsys.RunSession(testCfg) assert.Error(t, err) assert.Equal(t, core.NilSUUID(), actualSUUID) }, }, { - name: "Failure when adding invariant session to alerting system", + name: "Failure when adding heuristic session to alerting system", constructor: func(t *testing.T) *testSuite { ts := createTestSuite(t) ts.mockEtl.EXPECT(). ActiveCount().Return(1). Times(1) - ts.mockEng.EXPECT().DeployInvariantSession(testCfg). + ts.mockEng.EXPECT().DeployHeuristicSession(testCfg). Return(testSUUID, nil). Times(1) @@ -174,7 +174,7 @@ func Test_RunInvSession(t *testing.T) { return ts }, testLogic: func(t *testing.T, ts *testSuite) { - actualSUUID, err := ts.subsys.RunInvSession(testCfg) + actualSUUID, err := ts.subsys.RunSession(testCfg) assert.Error(t, err) assert.Equal(t, core.NilSUUID(), actualSUUID) }, @@ -188,7 +188,7 @@ func Test_RunInvSession(t *testing.T) { ActiveCount().Return(1). Times(1) - ts.mockEng.EXPECT().DeployInvariantSession(testCfg). + ts.mockEng.EXPECT().DeployHeuristicSession(testCfg). Return(testSUUID, nil). Times(1) @@ -203,7 +203,7 @@ func Test_RunInvSession(t *testing.T) { return ts }, testLogic: func(t *testing.T, ts *testSuite) { - actualSUUID, err := ts.subsys.RunInvSession(testCfg) + actualSUUID, err := ts.subsys.RunSession(testCfg) assert.NoError(t, err) assert.Equal(t, testSUUID, actualSUUID) }, @@ -213,7 +213,7 @@ func Test_RunInvSession(t *testing.T) { constructor: func(t *testing.T) *testSuite { ts := createTestSuite(t) - ts.mockEng.EXPECT().DeployInvariantSession(testCfg). + ts.mockEng.EXPECT().DeployHeuristicSession(testCfg). Return(testSUUID, nil). Times(1) @@ -225,7 +225,7 @@ func Test_RunInvSession(t *testing.T) { }, testLogic: func(t *testing.T, ts *testSuite) { testCfg.Reuse = true - actualSUUID, err := ts.subsys.RunInvSession(testCfg) + actualSUUID, err := ts.subsys.RunSession(testCfg) assert.NoError(t, err) assert.Equal(t, testSUUID, actualSUUID) }, @@ -243,7 +243,7 @@ func Test_RunInvSession(t *testing.T) { }, testLogic: func(t *testing.T, ts *testSuite) { testCfg.Reuse = false - actualSUUID, err := ts.subsys.RunInvSession(testCfg) + actualSUUID, err := ts.subsys.RunSession(testCfg) assert.Error(t, err) assert.Equal(t, core.NilSUUID(), actualSUUID) }, @@ -276,10 +276,10 @@ func Test_BuildPipelineCfg(t *testing.T) { return ts }, testLogic: func(t *testing.T, ts *testSuite) { - testParams := &models.InvRequestParams{ - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.BalanceEnforcement.String(), + testParams := &models.SessionRequestParams{ + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.BalanceEnforcement.String(), } cfg, err := ts.subsys.BuildPipelineCfg(testParams) @@ -298,10 +298,10 @@ func Test_BuildPipelineCfg(t *testing.T) { return ts }, testLogic: func(t *testing.T, ts *testSuite) { - testParams := &models.InvRequestParams{ - Network: "layer0", - PType: core.Live.String(), - InvType: core.BalanceEnforcement.String(), + testParams := &models.SessionRequestParams{ + Network: "layer0", + PType: core.Live.String(), + HeuristicType: core.BalanceEnforcement.String(), } cfg, err := ts.subsys.BuildPipelineCfg(testParams) @@ -320,10 +320,10 @@ func Test_BuildPipelineCfg(t *testing.T) { return ts }, testLogic: func(t *testing.T, ts *testSuite) { - testParams := &models.InvRequestParams{ - Network: core.Layer1.String(), - PType: core.Live.String(), - InvType: core.BalanceEnforcement.String(), + testParams := &models.SessionRequestParams{ + Network: core.Layer1.String(), + PType: core.Live.String(), + HeuristicType: core.BalanceEnforcement.String(), } cfg, err := ts.subsys.BuildPipelineCfg(testParams)