Skip to content

Conversation

@binarybaron
Copy link

@binarybaron binarybaron commented Jan 5, 2026

Excerpt from hermes.rs:

//! Hermes is an extension to the Monero protocol intended exclusively for use by the Eigenwallet Atomic Swap protocol.
//! 
//! It allows two parties (Alice and Bob) to communicate messages through a shared Monero wallet.
//! We use Monero to transmit small amounts of data between the parties as it can act as a reliable communication channel.
//! We only transmit a single message per swap so this should not have a significant impact on the chain.
//! We also commit the data on-chain such that either party can later construct a proof to allow another party that either one of the parties has acted in a certain way.
//! 
//! What is the difference to the Monero `PaymentId`s?
//! 1. The message size is not limited to 32 bytes. It could be up to 1060 bytes large but we limit it to 256 bytes to avoid bloating the chain unnecessarily.
//!    This is the primary reason for this custom extension. We need more to transmit around 162 bytes (> 32 bytes) of data.
//! 2. The message is encrypted using the private view key of the shared Monero wallet.
//!    This means it requires the sender to have knowledge of that key.
//!    PaymentIDs use the shared transaction secret.
//!    We use a different shared secret primarily because it simplifies the implementation.
//! 3. The extension could be modified to use a different shared secret that is negotiated off-chain.
//! 
//! Bob sends a message to Alice:
//! 
//! 1. Sending a transaction to the shared Monero wallet with a specially crafted `tx_extra` field that contains an encrypted message.
//! 0. Bob has
//! - his message `m`
//! - the private view key of the shared Monero wallet `v`
//! - the primary address of the shared Monero wallet `addr`
//! - the shared secret key `k` (by applying Keccak256 to the private view key `k = H(v)`)
//! 1. He concatenates: `HERMES_DATA_MARKER (u8) | `l` (length of m) (u16) | `m` | padding bytes until the limit is reached`.
//!    This yields the blob `b`.
//! 2. He generates a random 12-byte nonce `n` and encrypts `b` using ChaCha20 with key `k` and nonce `n`.
//! 2.1 The final encrypted blob is `e = nonce (12 bytes) || ChaCha20(k, n, b)`.
//! 3. He sets this as the `tx_extra` field of the transaction, adds an output of any amount to the shared wallet.
//! 4. He then signs the transaction and broadcasts it to the network.
//! 
//! Alice receives the message by:
//! 0. She computes the shared secret key by applying Keccak256 to the private view key `k = H(v)`
//! 1. Continuously scans the shared Monero wallet for incoming transactions.
//! 2. For each transaction, she extracts the nonce (first 12 bytes) and ciphertext from the `tx_extra` field.
//! 2.1 She decrypts the ciphertext using ChaCha20 with key `k` and the extracted nonce.
//! 2.2 She checks if the decrypted blob starts with the HERMES_DATA_MARKER.
//! 2.2 She then extracts the length of the message `l` from the decrypted blob. She then reads the next `l` bytes as the message `m`.
//! 2.3 Yields the message `m`.
//! 
//! Some notes:
//! - We could push the marker to the front of the already encrypted blob. This would allow Alice to avoid decrypting unnecessary data but it would make us even more fingerprintable.
//! - As we use monero-oxde arbitrary data tx_extra protocol, we will get an additional data marker in front of the encrypted blob. Preventing this would require patching the monero-oxide library.
//! - We add padding until we reach 256 bytes. This is also done to make us a little bit less fingerprintable by making all messages the same size.
//! - We could use steganography to hide the message in outputs but this bloats even more and is complex to implement

@binarybaron
Copy link
Author

binarybaron commented Jan 5, 2026

Is there value in having Bob commit to the hash of the encrypted signature? It could make verification for a third party a bit cheaper if Alice decides to spam messages into the shared wallet.

@binarybaron
Copy link
Author

binarybaron commented Jan 5, 2026

If we add a signature to the Hermes messages we'd need an additional ~75 bytes which would be too much. Or we'd have to go over the 254 bytes given to us by monero-oxide.

@binarybaron
Copy link
Author

This would work on a consensus level but if we can avoid it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants