Skip to main content

C API

Core concepts

There are two central objects in the event reader C API. They are:

  1. struct monad_event_ring - represents an event ring whose shared memory segments have been mapped into the address space of the current process; the primary thing the client does with this object is use it to initialize iterators that point into the event ring, using the monad_event_ring_init_iterator function
  2. struct monad_event_iterator - the star of the show: this iterator object is used to read sequential events. The iterator's try_next operation copies the next available event descriptor (if it is available) and if successful, advances the iterator. Conceptually, it behaves like the expression descriptor = *i++, if an event descriptor is ready immediately (it does nothing otherwise)

The easiest way to understand the API is to compile and run the included eventwatch example program. This program dumps ASCII representations of execution events to stdout, as they are written by a execution daemon running on the same host.

In eventwatch, the event descriptors are fully decoded, but the event payloads are only shown in hexdump form, because this simple program that does not include pretty-printing logic for all event payload types. The program is less than 250 lines of code, and reading through it should explain how the various API calls fit together.

The SDK also includes C++20 std::formatter specializations which can fully decode event payloads into human-readable form. These are used by the eventcap utility program.

Using the API in your project

libmonad_event is designed for third party integration, so it does not have any library dependencies aside from a recent version of glibc. This also means it has no dependency on the rest of the monad repository or on its build system: the sole requirement is a C compiler supporting C23.

The "Getting start" guide to building the C example program discusses several ways to use the SDK library as a third-party dependency in your code. Alternatively, the source files that make up the library target can be copied into your own codebase. A Rust client library is also available.

Event ring APIs

APIPurpose
monad_event_ring_mmapGiven a file descriptor to an open event ring file, map its shared memory segments into the current process, initializing a struct monad_event_ring
monad_event_ring_init_iteratorGiven a pointer to a struct monad_event_ring, initialize an iterator that can be used to read from the event ring
monad_event_ring_try_copyGiven a specific sequence number, try to copy the event descriptor for it, if it hasn't been overwritten
monad_event_ring_payload_peekGet a zero-copy pointer to an event payload
monad_event_ring_payload_checkCheck if an event payload referred to by a zero-copy pointer has been overwritten
monad_event_ring_memcpymemcpy the event payload to a buffer, succeeding only if the payload is not expired
monad_event_ring_get_last_errorReturn a human-readable string describing the last error that occurred on this thread

All functions which can fail will return an errno(3) domain error code diagnosing the reason for failure. The function monad_event_ring_get_last_error can be called to provide a human-readable string explanation of what failed.

Event iterator APIs

APIPurpose
monad_event_iterator_try_nextIf the next event descriptor if is available, copy it and advance the iterator
monad_event_iterator_try_copyCopy the event descriptor at the current iteration point, without advancing the iterator
monad_event_iterator_resetReset the iterator to point to the most recently produced event descriptor; used for gap recovery
monad_exec_iter_consensus_prevRewinds an iterator to the previous consensus event (BLOCK_START, BLOCK_QC, BLOCK_FINALIZED, or BLOCK_VERIFIED)
monad_exec_iter_block_number_prevRewinds an iterator to the previous consensus event for the given block number
monad_exec_iter_block_id_prevRewinds an iterator to the previous consensus event for the given block ID
monad_exec_iter_rewind_for_simple_replayRewinds an iterator to replay events you may have missed, based on the last finalized block you saw

Library organization

Event ring files in libmonad_event:

FileContains
event_ring.{h,c}Definitions of core shared memory structures for event rings, and the API that initializes and mmaps event ring files
event_iterator.hDefines the basic event iterator object and its API
event_iterator_inline.hDefinitions of the event_iterator.h functions, all of which are inlined for performance reasons
event_metadata.hStructures that describe event metadata (string names of events, descriptions of events, etc.)
exec_iter_help.hAPI for rewinding the the iterator to point to block executions or consensus events

Execution event files in libmonad_event:

FileContains
base_ctypes.hDefinitions of basic vocabulary types common in Ethereum data (e.g., 256 bit integer types, etc).
eth_ctypes.hDefinitions of structures used in the Ethereum virtual machine
exec_event_ctypes.hDefinition of execution event payload structures, and the event type enumeration enum monad_exec_event_type
exec_event_ctypes_metadata.cDefines static metadata about execution events, and the schema hash value array
monad_ctypes.hDefinitions of Monad blockchain extensions to Ethereum

Supporting files in libmonad_event:

FileContains
event_ring_util.{h,c}Convenience functions that are useful in most event ring programs, but which are not part of the core API
format_err.{h,c}Helper utility from the execution codebase used to implement the monad_event_ring_get_last_error() function
srcloc.hHelper utility used with the format_err.h API, for capturing source code locations in C

Other files in the SDK:

FileContents
eventwatch.cA sample program that shows how to use the API
*_fmt.hpp filesFiles ending in _fmt.hpp are used with C++ <format> and contain std::formatter specializations for SDK types
hex.hpp<format> hexdump utility used by the _fmt.hpp files to dump uint8_t[] values