diff --git a/price_service/server-rust/.gitignore b/hermes/.gitignore similarity index 100% rename from price_service/server-rust/.gitignore rename to hermes/.gitignore diff --git a/price_service/server-rust/Cargo.lock b/hermes/Cargo.lock similarity index 99% rename from price_service/server-rust/Cargo.lock rename to hermes/Cargo.lock index e27cd0fb..d6c4fd84 100644 --- a/price_service/server-rust/Cargo.lock +++ b/hermes/Cargo.lock @@ -1453,6 +1453,38 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermes" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "axum-macros", + "bs58", + "dashmap", + "der 0.7.0", + "env_logger", + "futures", + "hex", + "lazy_static", + "libc", + "libp2p", + "log", + "rand 0.8.5", + "reqwest", + "ring", + "rusqlite", + "secp256k1", + "serde", + "serde_arrays", + "serde_cbor", + "serde_json", + "sha256", + "structopt", + "tokio", + "typescript-type-def", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -2940,38 +2972,6 @@ dependencies = [ "syn", ] -[[package]] -name = "price-service" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum", - "axum-macros", - "bs58", - "dashmap", - "der 0.7.0", - "env_logger", - "futures", - "hex", - "lazy_static", - "libc", - "libp2p", - "log", - "rand 0.8.5", - "reqwest", - "ring", - "rusqlite", - "secp256k1", - "serde", - "serde_arrays", - "serde_cbor", - "serde_json", - "sha256", - "structopt", - "tokio", - "typescript-type-def", -] - [[package]] name = "proc-macro-crate" version = "1.1.3" diff --git a/price_service/server-rust/Cargo.toml b/hermes/Cargo.toml similarity index 97% rename from price_service/server-rust/Cargo.toml rename to hermes/Cargo.toml index fa3db0b8..302f226c 100644 --- a/price_service/server-rust/Cargo.toml +++ b/hermes/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "price-service" +name = "hermes" version = "0.1.0" edition = "2021" diff --git a/hermes/README.md b/hermes/README.md new file mode 100644 index 00000000..0a163ca4 --- /dev/null +++ b/hermes/README.md @@ -0,0 +1,200 @@ +# Hermes + +Hermes is a highly available and versatile software that defines the Pyth P2P +network. It also provides the public Pyth API and connects with the Pyth Geyser +node software to listen for Pythnet events. Hermes offers both REST and +WebSocket APIs for seamless integration and interaction with the Pyth network +stack. Anyone can run the Node to: + +1. Provide their own Pyth API for interacting with the Pyth Network stack. +2. Observe Pyth price updates in real-time. +3. Operate alongside their Pythnet validator for fully decentralized access to Pyth. + +## Getting Started + +To set up and run a Hermes node, follow the steps below: + +1. **Install Rust**: If you haven't already, you'll need to install Rust. You can + do so by following the official instructions. +2. **Install Go**: If you haven't already, you'll also need to install Go. You can + do so by following the official instructions. +3. **Clone the repository**: Clone the Pyth Crosschain repository to your local + machine using the following command: + ```bash + git clone https://github.com/pyth-network/pyth-crosschain.git + ``` +4. **Build the project**: Navigate to the project directory and run the following command to build the project: + ```bash + cd hermes + cargo build --release + ``` + This will create a binary in the target/release directory. +5. **Run the node**: To run Hermes, use the following command: + ```bash + ./target/release/hermes run --geyser-socket /tmp/geyser.ipc + ``` + Your Hermes node will now start and connect to the specified networks. You + can interact with the node using the REST and Websocket APIs as described + in the [API Documentation](). You can leave off the `--geyser-socket` arg + if you are planning to run the node without a Pythnet validator, it will + extract data only from the Pyth P2P network. Running a Pythnet node will + improve the speed and accuracy of network observations. + +## Architecture Overview + +For users who simply want to run the software, this section can be skipped. +However, for those interested in understanding Pyth's architecture, this +section explains the old and new architecture, as well as our motivation for +the design. + +### Background + +The Pyth project offers a cross-chain price oracle service for real-time access +to current prices of real-world assets. These prices are aggregated on Pythnet, +where core Pyth contracts are hosted, and pricing information is generated. The +Wormhole project currently sends these prices to other chains. + +To share these prices, the Pyth project provides a standalone application +called the Price Service, which queries the message API provided by Wormhole to +look for Pyth prices. + +The original communication flow can be visualized in the following graph: + +``` + +--------+ +--------+ +--------+ + | User 3 | | User 2 | | User 1 | + +--------+ +--------+ +--------+ + | | | + | | | + +--------------+--------------+ + | + v + +---------------------+ + | Price Service | (Weakly Decentralised) + +----------+----------+ + | + v + +---------------------+ + | Wormhole | (Decentralised) + +---------------------+ + ^ + | + v + + - - - - - - - - - + - - - - - - - - - - - + + ' Pythnet ' + ' ' + ' +----------------+ ' + ' | Pythnet Node 1 | ------+ ' + ' +----------------+ | ' + ' | | ' + ' | | ' + ' +----------------+ | ' (Decentralised) + ' | Pythnet Node 2 | | ' + ' +----------------+ | ' + ' | | ' + ' | | ' + ' +----------------+ +----------------+ ' + ' | Pythnet Node 3 | --- | Pythnet Node 4 | ' + ' +----------------+ +----------------+ ' + + - - - - - - - - - - - - - - - - - - - - - + +``` + +This design has issues due to latency and API complexity introduced by the +Price Service, which acts as a middleman between the user, Wormhole, and +Pythnet. Additionally, it does not represent a particularly decentralized +design, which was a weak point for Pyth. + +### New Model + +In the new model, we designed a single node-style service, Hermes, intended for +direct integration into Pythnet nodes. This aligns with other blockchain +projects where running standard node software allows users to act as observers +of the network: + +``` + +--------+ +--------+ +--------+ + | User 3 | | User 2 | | User 1 | + +--------+ +--------+ +--------+ + | | | + | | | + +--------------+--------------+ + | + v + + - - - - - - - - - + - - - - - - - - - - - + + ' Pythnet ' + ' ' + ' +----------------+ ' + ' | Pythnet Node 1 | ------+ ' + ' +----------------+ | ' + ' | |Hermes| | ' + ' | +------+ | ' + ' | | ' + ' +----------------+ | ' + ' | Pythnet Node 2 | | ' + ' +----------------+ | ' + ' | |Hermes| | ' + ' | +------+ | ' + ' | | ' + ' +----------------+ +----------------+ ' + ' | Pythnet Node 3 | --- | Pythnet Node 4 | ' + ' +----------------+ +----------------+ ' + ' |Hermes| |Hermes| ' + ' +------+ +------+ ' + + - - - - - - - - - - - - - - - - - - - - - + + ^ + | + v + +---------------------+ + | Wormhole | + +---------------------+ +``` + +In this new design, the Price Service is integrated into the Hermes node +service, decentralizing the API. Hermes is now also responsible for direct +communication with Wormhole over P2P, which reduces latency and simplifies +responsibilities. + +The new design offers several benefits: + +1. Hermes can participate as a P2P node in the Wormhole network directly. +2. Hermes nodes form a Pyth-specific P2P network with fast communication. +3. Hermes can directly observe on-chain state for faster operation. +4. Hermes can have its identity tied to a Pythnet node for authenticated operation. +5. Data ownership is clearer with the removal of the middleman. + +With tighter communication flow, we can define new behaviors such as +Pyth-specific threshold signing, fast price accumulation with proving (due to +direct node access), improved metrics and observations, and the ability for +users to run observe-only Hermes nodes to watch the Pyth network directly +instead of relying on a Price Service host. + +The Hermes node architecture is as follows: + +--- + +![image](https://user-images.githubusercontent.com/158967/225939587-f19cfe77-0393-4798-ad72-0022420d3e51.png) + +--- + +This is more in line with other well-known projects in the blockchain and P2P +space, such as Solana, Bitcoin, and Cosmos chains, where users who run the node +can also act as observers with specific features disabled. + +In our case, the node software can be run with or without a Pythnet validator +running due to it being designed to fetch updates from either Pyth or Geyser +networks for high availability. + +## Components + +The Hermes Node software consists of the following components: + +- **Wormhole P2P Connector**: Connects to the Wormhole P2P network and listens for VAAs. +- **Pyth P2P Connector**: Connects to the Pyth P2P network and listens for Account Updates. +- **Geyser Connector**: Connects to the Geyser node software and listens for Account Updates. +- **REST API**: Provides an interface for external applications to interact with Pythnet. +- **Websocket API**: Offers real-time data streaming for interacting with Pythnet. + +While Hermes will always participate in the Wormhole and Pyth P2P networks, the +Pyth network shares network updates on the Pyth layer and so can be run without +a Pythnet node running along-side it for a spy-only mode. This can be done by +running without specifying `--geyser-socket`. diff --git a/price_service/server-rust/buf.gen.yaml b/hermes/buf.gen.yaml similarity index 100% rename from price_service/server-rust/buf.gen.yaml rename to hermes/buf.gen.yaml diff --git a/price_service/server-rust/build.rs b/hermes/build.rs similarity index 100% rename from price_service/server-rust/build.rs rename to hermes/build.rs diff --git a/price_service/server-rust/go.mod b/hermes/go.mod similarity index 100% rename from price_service/server-rust/go.mod rename to hermes/go.mod diff --git a/price_service/server-rust/go.sum b/hermes/go.sum similarity index 100% rename from price_service/server-rust/go.sum rename to hermes/go.sum diff --git a/price_service/server-rust/shell.nix b/hermes/shell.nix similarity index 100% rename from price_service/server-rust/shell.nix rename to hermes/shell.nix diff --git a/price_service/server-rust/src/config.rs b/hermes/src/config.rs similarity index 100% rename from price_service/server-rust/src/config.rs rename to hermes/src/config.rs diff --git a/price_service/server-rust/src/main.rs b/hermes/src/main.rs similarity index 100% rename from price_service/server-rust/src/main.rs rename to hermes/src/main.rs diff --git a/price_service/server-rust/src/network.rs b/hermes/src/network.rs similarity index 100% rename from price_service/server-rust/src/network.rs rename to hermes/src/network.rs diff --git a/price_service/server-rust/src/network/p2p.go b/hermes/src/network/p2p.go similarity index 100% rename from price_service/server-rust/src/network/p2p.go rename to hermes/src/network/p2p.go diff --git a/price_service/server-rust/src/network/p2p.rs b/hermes/src/network/p2p.rs similarity index 100% rename from price_service/server-rust/src/network/p2p.rs rename to hermes/src/network/p2p.rs diff --git a/price_service/server-rust/src/network/rpc.rs b/hermes/src/network/rpc.rs similarity index 100% rename from price_service/server-rust/src/network/rpc.rs rename to hermes/src/network/rpc.rs diff --git a/price_service/server-rust/src/network/rpc/rest.rs b/hermes/src/network/rpc/rest.rs similarity index 100% rename from price_service/server-rust/src/network/rpc/rest.rs rename to hermes/src/network/rpc/rest.rs