This is a C++ library for encoding and decoding data in the Recursive Length Prefix (RLP) format, as used in Ethereum and other blockchain systems. It provides a robust, type-safe implementation with support for basic types (Bytes, uint64_t, uint256, bool), lists, and convenience methods for vectors and fixed-size arrays.
- Encoding: Supports RLP encoding of raw bytes, unsigned integers (
uint8_ttouint256), booleans, and nested lists. - Decoding: Decodes RLP data into corresponding C++ types, with error handling for malformed inputs.
- Type Safety: Uses C++17 SFINAE and templates to ensure correct type handling.
- Cross-Platform: Build instructions provided for multiple platforms using Ninja and CMake.
- C++17: Required for template features and type traits.
- Boost.Outcome: Used for error handling (
BOOST_OUTCOME_TRY). - Google Test: For unit tests (
gtest). - intx: Extended precision integer library for
uint256support.
src/: Source files (rlp_encoder.cpp,rlp_decoder.cpp, etc.).include/: Header files (rlp_encoder.hpp,rlp_decoder.hpp, etc.).test/: Unit tests (rlp_test.cpp).build/: Platform-specific build directories (e.g.,build/OSX/,build/Linux/).
This project uses Ninja as the build system, with CMake for configuration. Builds are organized in platform-specific directories under build/, such as build/OSX/ for macOS, build/Linux/ for Linux, etc. Each platform directory contains subdirectories for build configurations (Debug, Release, RelWithDebInfo).
- Install CMake (
cmake). - Install Ninja (
ninja). - Ensure C++17-compatible compiler (e.g.,
g++,clang++). - Install dependencies:
- Boost (
boost-outcomeor full Boost suite). - Google Test (
libgtest-devon Ubuntu, or build from source). - intx (include as a submodule or install separately).
- Boost (
Builds are always run from inside the build/<Platform>/<BuildType>/ directory.
cmake .. points to build/<Platform>/ which contains the platform CMakeLists.
Never run cmake from the repo root or build/<Platform>/ directly.
cd build/OSX
mkdir -p Debug && cd Debug
cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Debug
ninjacd build/OSX
mkdir -p Release && cd Release
cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Release
ninjacd build/OSX
mkdir -p RelWithDebInfo && cd RelWithDebInfo
cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=RelWithDebInfo
ninjaThe optional -DSANITIZE_ADDRESS=code flag enables AddressSanitizer for memory leak detection.
If the build directory is ever deleted or CMakeCache.txt goes stale:
cd build/OSX rm -rf Debug # or Release / RelWithDebInfo mkdir Debug && cd Debug cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ninjaDo not delete the cache and re-run cmake in-place with a different source path — always recreate the directory and let
cmake ..resolve everything frombuild/<Platform>/.
- Output: Built files are in
build/OSX/Debug/,build/OSX/Release/, etc. - Platforms: Replace
OSXwithLinux,Windows,Android, oriOSas needed.
After building, run the test executable:
cd build/OSX/Debug
./rlp_test#include <rlp_encoder.hpp>
int main() {
rlp::RlpEncoder encoder;
encoder.begin_list();
encoder.add(42); // uint64_t
encoder.add(true); // bool
encoder.end_list();
rlp::Bytes encoded = encoder.move_bytes();
// encoded contains RLP-encoded list [42, true]
return 0;
}#include <rlp_decoder.hpp>
int main() {
rlp::Bytes data = /* some RLP data */;
rlp::RlpDecoder decoder(data);
auto list_payload_bytes = decoder.read_list_header_bytes(); // Returns byte count, not item count
if (list_payload_bytes) {
uint64_t num;
bool flag;
decoder.read(num);
decoder.read(flag);
// Use num and flag
}
return 0;
}The repository now contains the core building blocks required by the architecture design for running a SuperGenius light client that monitors contract activity directly from EVM P2P networks. The implementation spans three cooperating layers that map directly to the design’s stages:
- Located under
include/rlp/PeerDiscovery/andsrc/rlp/PeerDiscovery/, the discovery module RLP-encodes/decodes v4 packets, manages bootstrap node metadata, and orchestrates UDP flows via Boost.Asio, mirroring the design’s discovery responsibilities. - Unit coverage in
test/discv4/discovery_test.cppexercises PING/PONG construction, parsing, and timeout handling to validate the discovery flow end-to-end.
- The
rlpxsubsystem (include/rlpx/andsrc/rlpx/) implements the secure TCP transport, including ECIES handshakes, AES/HMAC frame ciphers, message framing, and coroutine-based session orchestration—directly covering the RLPx andethsubprotocol requirements from the design. - High-level session APIs expose message handlers for HELLO, STATUS, PING, and generic gossip, enabling the transaction/log filtering pipeline described in the design document.
- Core encoding/decoding utilities in
include/rlp/andsrc/rlp/provide the recursive RLP handling needed to parse block headers, transactions, and receipts once they are received over the wire, satisfying the design’s execution-layer processing goals. include/rlp/rlp_ethereum.hppsupplies Ethereum-specific helpers (e.g., for block header fields and bloom filters) that align with the consensus verification and log filtering steps laid out in the design.
These components can be composed inside SuperGenius to establish DevP2P connections, validate chain consistency from checkpoints, and stream contract events without centralized RPC endpoints.
The project includes comprehensive unit tests covering RLP encoding/decoding, RLPx crypto, ETH message handling, discv4 discovery, and more (499 tests total).
cd build/OSX/Debug
ctest --no-pagereth_watch connects directly to Ethereum P2P networks via discv4 + RLPx — no RPC
required. The test scripts below watch for GNUS.AI contract events across multiple
chains and can send test transactions to verify end-to-end detection.
Install Foundry for the cast tool (used to
sign and send transactions):
brew install foundryRun once to create a dedicated test wallet and save it to a local .env file.
.env is git-ignored — never commit it.
cast wallet new --json | \
node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); \
console.log('# Test wallet — DO NOT COMMIT\nPRIVATE_KEY='+d[0].private_key+'\nTEST_ADDRESS='+d[0].address);" \
> .env && cat .envSend a small amount of GNUS to TEST_ADDRESS (shown in .env) on each chain you
want to test, from your own wallet. GNUS contract addresses:
| Chain | Address |
|---|---|
| Ethereum | 0x614577036F0a024DBC1C88BA616b394DD65d105a |
| Polygon | 0x127E47abA094a9a87D084a3a93732909Ff031419 |
| BSC | 0x614577036F0a024DBC1C88BA616b394DD65d105a |
| Base | 0x614577036F0a024DBC1C88BA616b394DD65d105a |
| Ethereum Sepolia | 0x9af8050220D8C355CA3c6dC00a78B474cd3e3c70 |
| Polygon Amoy | 0xeC20bDf2f9f77dc37Ee8313f719A3cbCFA0CD1eB |
| BSC Testnet | 0xeC20bDf2f9f77dc37Ee8313f719A3cbCFA0CD1eB |
| Base Sepolia | 0xeC20bDf2f9f77dc37Ee8313f719A3cbCFA0CD1eB |
Source: docs.gnus.ai/resources/contracts
In one terminal, start the watcher before sending transactions so events are caught live:
# All 4 mainnets
./test_eth_watch.sh
# All 4 testnets
./test_eth_watch.sh gnus-all-testnets
# Single chain
./test_eth_watch.sh polygonIn a second terminal, send a GNUS Transfer from the test wallet:
# Testnets
source .env && ./send_test_transactions.sh testnets
# Mainnets
source .env && ./send_test_transactions.sh
# Specific chains
source .env && ./send_test_transactions.sh sepolia polygon-amoyOptional env var overrides:
# Send to a different address
TO_ADDRESS=0x... source .env && ./send_test_transactions.sh testnets
# Use your own RPC endpoint
RPC_SEPOLIA=https://my-node.example.com source .env && ./send_test_transactions.sh sepolia
# Extend the watch window (default 60s)
WATCH_TIMEOUT=120 ./test_eth_watch.sh gnus-all-testnets[Sepolia ] HELLO from peer: Geth/v1.16.7-stable/linux-amd64/go1.25.1
[Sepolia ] ETH STATUS: network_id=11155111
[Sepolia ] NewBlockHashes: 1 hashes
[Sepolia ] Transfer(0xYourAddress → 0xTestAddress, 1) at block 7654321
- Fork the repository.
- Create a feature branch.
- Submit a pull request with your changes and updated tests.
This project is licensed under the MIT License. See LICENSE.txt for details.