Oura is a tool for pool operators, developers, and anyone who wants to find information on the blockchain.
There are currently tools for exploring the Cardano blockchain, which are useful when looking for standardized or generic information, but the Oura use case is complementary, looking at the blockchain for patterns of particular events.
Oura is, in essence, a tool to process information from certain events. A pipeline that connects to the tail of a Cardano node, via some Ouroboros mini-protocol combination (using a unix socket or tcp bearer), filters events that match a particular pattern, and then sends a payload succinct, self-contained utility to pluggable observers called “sinks.”
Oura is a native implementation of Rust, which is a lightweight, compiled, general-purpose, multi-paradigm programming language that supports pure functional, procedural, imperative, and object-oriented programming.
Oura is open source and licensed under the Apache-2.0 license.
This tool processes the events in stages, and each one fulfills a different function, which I will explain later.
Ouroboros, the Cardano consensus protocol, is a reference to the ancient symbol that represents a serpent or dragon eating its own tail. The term Oura is of Greek etymology, and means “tail”. The tool is inspired by the “tail” command available on Unix-like systems, which is used to display the tail of a text file or piped data.
How Oura Works
All of the heavy lifting required to communicate with the Cardano node is done by the Pallas, which provides an implementation of the Ouroboros multiplixer and some of the necessary mini-protocol state machines (ChainSync and LocalState in particular).
Pallas is an expanding collection of modules that re-implements common Cardano logic in native Rust. This crate doesn’t provide any particular application, it is meant to be used as a base layer to facilitate the development of higher-level use-cases, such as explorers, wallets, etc (who knows, maybe even a full node in the far away future).
The data pipe makes heavy use of the multithreading and mpsc pipes provided by the Rust std::sync library.
Oura connects directly to the Cardano node using TCP or Unix sockets.
Each stage of the pipeline plays a different role:
Source Stages: is responsible for extracting the data from the blockchain, and mapping the raw blocks, in search of smaller and more granular events. Each event is then sent through the stage’s output port for further processing.
Filter Stages– Receive individual events from the source and apply transformations to each of them. The applied transformations will depend on the particular use case, but they usually revolve around the selection of relevant events and their enrichment with additional information, selecting the relevant events, enriching the events with external information, adding metrics, etc.
Sink Stages: receives the final version of the events and sends the payload to an external system, database, or service for further processing. For example: Kafka, Elasticsearch, or a custom HTTP endpoint. Oura allows you to use one of the built-in sinks or create your own.
The following diagram describes the data flow, starting from the Cardano node, until reaching the searching user through the web interface.
Terminal output demo
In this terminal recording we can see a few minutes of live output from a testnet node connected to the terminal sink: https://asciinema.org/a/453455
Command line interface (CLI) to view transactions live
The CLI tool of the node is the “Swiss Army Knife” of the system, which allows querying the node to obtain information, send transactions, build and sign transactions, and manage cryptographic keys. Using the CLI, Oura can call watch <socket> to print TX data to the terminal from the tip of a local or remote node. It can be useful as a debugging tool for developers, or just to see what’s happening on the network (e.g. to watch airdrops as they happen or oracles posting new information).
As a bridge to other persistence mechanisms
Like the well-known db-sync tool provided by IOHK, Oura can be used as a “daemon” (a special type of program that runs in the background) to follow a node, and send data to it. data to a different data storage technology more suitable for your end use case. The main difference from db-sync is that Oura was designed for easy integration with data flow pipelines rather than relational databases.
Given its small memory/cpu footprint, Oura can be deployed alongside your Cardano node even in resource-constrained environments such as Raspberry PIs.
As a custom action trigger
Oura, in “daemon” mode, can be configured to use custom filters to identify particular transaction patterns, and trigger actions when a match is found. For example: send an email when a particular policy/asset combination appears in a transaction; call an AWS Lambda function when a wallet delegates to a particular pool; send an http call to a webhook every time a metadata key appears in the TX payload.
As a library for custom scenarios
If the available features don’t suit your particular use case, Oura can be used as a library in the Rust project to configure custom pipelines. Each component (sources, filters, sinks, etc.) of Oura is intended to be self-contained and reusable. For example, custom filters and sinks can be built by reusing existing sources.
support Oura’s Windows support is currently experimental, the Windows build only supports Node-to-Node source with tcp socket bearer.
One of the potential use-cases for Oura is scraping metadata. This is a reference app to show how Oura can be leveraged to build a search engine for CIP-25 tokens.
The frontend is built using React and Remix. The backend is a combination of a Cardano node, Oura, and Elasticsearch. Everything together is deployed using Kubernetes.
Live demo: https://cip25-search-engine.txpipe.io
For Experts: Installation
Oura provides different installation options:
- Binary Release: to use one of our pre-compiled binary releases for the supported platforms.
- From Source: to compile a binary from source code using Rust’s toolchain
- Docker: to run the tool from a pre-built docker image
- Kubernetes: to deploy Oura as a resource within a Kuberentes cluster
Currently Oura has certain limitations, that’s why the development team is working on certain improvements.
Oura can only process blocks from the Shelley era, so the developers are working to add support for Byron, before the current Shelley era, in a future release.
Oura reads minted block/transaction events. Support for querying the mempool is planned for a future release.
Oura will report chain backtracking as a new event. The business logic to “undo” already processed events is the responsibility of the consumer. The team will add support for a “buffer” filter stage that can retain blocks until they reach a configurable depth (number of confirmations).
The latest release v1.1.0 of Oura.
Santiago Carmuega is Argentinian and leader of the project. His main collaborator is Mark Stopka. You can see the full team here.
dcSpark started contributing to both Pallas and Oura. For Pallas, Nicolas Di Prima contributed pallas-crypto crate and $rvcas started working on pallas-byron which will enable to decode old Cardano Byron era blocks.