> For the complete documentation index, see [llms.txt](https://docs.seismic.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.seismic.systems/clients/alloy/transaction-types/tx-seismic-elements.md).

# TxSeismicElements

Encryption metadata attached to every `TxSeismic` transaction. Contains the public key, nonce, signing mode, freshness proof, expiry, and read/write flag required for Seismic's AEAD encryption scheme.

## Overview

`TxSeismicElements` carries all encryption and security parameters needed for a Seismic transaction. These fields enable ECDH key derivation, AES-GCM encryption, anti-replay protection, and transaction expiration. The filler pipeline (`SeismicElementsFiller`) populates these fields automatically when a `ShieldedCallBuilder` is used (either via auto-encryption for functions with shielded params, or via `.seismic()`).

## Definition

```rust
pub struct TxSeismicElements {
    pub encryption_pubkey: PublicKey,     // secp256k1 compressed pubkey (33 bytes)
    pub encryption_nonce: U96,           // 12-byte nonce for AES-GCM
    pub message_version: u8,             // 0=RLP, >=2=EIP-712
    pub recent_block_hash: B256,         // anti-replay
    pub expires_at_block: u64,           // expiration block
    pub signed_read: bool,               // true for signed reads
}
```

## Fields

| Field               | Type        | Description                                                                                    |
| ------------------- | ----------- | ---------------------------------------------------------------------------------------------- |
| `encryption_pubkey` | `PublicKey` | Compressed secp256k1 public key (33 bytes) used for ECDH shared secret derivation with the TEE |
| `encryption_nonce`  | `U96`       | 12-byte random nonce for AES-GCM encryption. Must be unique per transaction                    |
| `message_version`   | `u8`        | Signing mode: `0` for raw RLP hash signing, `2` or higher for EIP-712 typed data signing       |
| `recent_block_hash` | `B256`      | Hash of a recent block, proving the transaction was created recently (freshness proof)         |
| `expires_at_block`  | `u64`       | Block number after which the transaction is invalid. Prevents delayed execution                |
| `signed_read`       | `bool`      | `true` for signed `eth_call` reads (no state change), `false` for write transactions           |

## Default Values

```rust
impl Default for TxSeismicElements {
    fn default() -> Self {
        Self {
            encryption_pubkey: /* hardcoded default public key */,
            encryption_nonce: U96::ZERO,
            message_version: 0,
            recent_block_hash: B256::ZERO,
            expires_at_block: 0,
            signed_read: false,
        }
    }
}
```

{% hint style="info" %}
Default values are placeholders. The `SeismicElementsFiller` replaces them with real values (TEE public key, random nonce, latest block hash, current block + window) before the transaction is sent.
{% endhint %}

## Builder Methods

`TxSeismicElements` provides a builder pattern for constructing instances:

| Method                     | Signature                                                    | Description                             |
| -------------------------- | ------------------------------------------------------------ | --------------------------------------- |
| `with_encryption_pubkey()` | `fn with_encryption_pubkey(self, pubkey: PublicKey) -> Self` | Set the encryption public key           |
| `with_encryption_nonce()`  | `fn with_encryption_nonce(self, nonce: U96) -> Self`         | Set the AES-GCM nonce                   |
| `with_message_version()`   | `fn with_message_version(self, version: u8) -> Self`         | Set the signing mode (0=RLP, 2=EIP-712) |
| `with_recent_block_hash()` | `fn with_recent_block_hash(self, hash: B256) -> Self`        | Set the freshness block hash            |
| `with_expires_at_block()`  | `fn with_expires_at_block(self, block: u64) -> Self`         | Set the expiration block number         |
| `with_signed_read()`       | `fn with_signed_read(self, signed_read: bool) -> Self`       | Set the read/write flag                 |

### Example

```rust
use seismic_alloy_consensus::{TxSeismicElements, SeismicTransactionRequest};
use alloy::primitives::{B256, U96};

let elements = TxSeismicElements::default()
    .with_encryption_pubkey(tee_pubkey)
    .with_encryption_nonce(U96::from(random_nonce))
    .with_message_version(2)
    .with_recent_block_hash(latest_block_hash)
    .with_expires_at_block(current_block + 100)
    .with_signed_read(false);
```

## Static Helpers

| Function                        | Signature                                     | Description                                        |
| ------------------------------- | --------------------------------------------- | -------------------------------------------------- |
| `get_rand_encryption_keypair()` | `fn get_rand_encryption_keypair() -> Keypair` | Generate a random secp256k1 keypair for encryption |
| `get_rand_encryption_nonce()`   | `fn get_rand_encryption_nonce() -> U96`       | Generate a random 12-byte AES-GCM nonce            |

### Example

```rust
use seismic_alloy_consensus::{TxSeismicElements, SeismicTransactionRequest};

// Generate random encryption keypair
let keypair = TxSeismicElements::get_rand_encryption_keypair();

// Generate random nonce
let nonce = TxSeismicElements::get_rand_encryption_nonce();
```

## Crypto Methods

`TxSeismicElements` provides methods for encrypting and decrypting calldata using AEAD (AES-GCM with additional authenticated data).

### Low-Level Encryption

| Method                              | Signature                                                                                                               | Description                                                   |
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `encrypt(sk, plaintext, metadata)`  | `fn encrypt(&self, sk: &SecretKey, plaintext: &Bytes, metadata: &TxSeismicMetadata) -> Result<Bytes, anyhow::Error>`    | Encrypt plaintext using ECDH-derived key and metadata as AAD  |
| `decrypt(sk, ciphertext, metadata)` | `fn decrypt(&self, sk: &SecretKey, ciphertext: &Bytes, metadata: &TxSeismicMetadata) -> Result<Vec<u8>, anyhow::Error>` | Decrypt ciphertext using ECDH-derived key and metadata as AAD |

### Client-Side Encryption

| Method                                                        | Signature                                                                                                                                                     | Description                                        |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| `client_encrypt(plaintext, network_pk, client_sk, metadata)`  | `fn client_encrypt(&self, plaintext: &Bytes, network_pk: &PublicKey, client_sk: &SecretKey, metadata: &TxSeismicMetadata) -> Result<Bytes, anyhow::Error>`    | Client-side encrypt using network (TEE) public key |
| `client_decrypt(ciphertext, network_pk, client_sk, metadata)` | `fn client_decrypt(&self, ciphertext: &Bytes, network_pk: &PublicKey, client_sk: &SecretKey, metadata: &TxSeismicMetadata) -> Result<Vec<u8>, anyhow::Error>` | Client-side decrypt using network (TEE) public key |

### Encryption Flow

```
Client                          TEE (Node)
  |                               |
  |  1. ECDH(client_sk, tee_pk)  |
  |  -> shared_secret             |
  |                               |
  |  2. AES-GCM encrypt:         |
  |     key = shared_secret       |
  |     nonce = encryption_nonce  |
  |     aad = TxSeismicMetadata   |
  |     -> ciphertext             |
  |                               |
  |  3. Send TxSeismic ---------->|
  |                               |
  |     4. ECDH(tee_sk, client_pk)|
  |     -> same shared_secret     |
  |                               |
  |     5. AES-GCM decrypt        |
  |     -> plaintext calldata     |
```

## Field Details

### encryption\_pubkey

The compressed secp256k1 public key (33 bytes) used in the ECDH key exchange. For client-initiated transactions, this is the **client's provider-scoped public key** — the TEE uses its own private key combined with this public key to derive the shared encryption secret.

### encryption\_nonce

A 12-byte (96-bit) random value used as the nonce for AES-GCM encryption. Must be unique for every transaction to prevent nonce reuse attacks. Generated automatically by the filler pipeline via `get_rand_encryption_nonce()`.

### message\_version

Controls the signing method:

* **`0`** — Raw signing: the signing hash is computed from the RLP encoding of the unsigned transaction
* **`2` or higher** — EIP-712 signing: the signing hash is computed from structured typed data

The default value is `0` (raw RLP signing). Set `message_version = 2` for EIP-712 typed data signing.

### recent\_block\_hash

Hash of a recent block from the canonical chain. The node verifies this hash exists in its chain, ensuring the transaction was created recently and is not a stale replay. Auto-populated by `SeismicElementsFiller`.

### expires\_at\_block

The block number after which the transaction is rejected by the node. Typically set to `current_block + 100` (about 200 seconds on a 2-second block time). Prevents transactions from being held and executed much later.

### signed\_read

* **`false`** — This is a write transaction that will be broadcast and modify state
* **`true`** — This is a signed `eth_call` for reading private state without state modification

The filler pipeline sets this based on whether you call `send_transaction()` or `seismic_call()`.

## Examples

### Automatic Construction (Typical)

```rust
use seismic_alloy_consensus::{TxSeismicElements, SeismicTransactionRequest};

// The filler pipeline handles TxSeismicElements construction
let tx = SeismicTransactionRequest::default()
    .with_input(calldata.into())
    .with_kind(TxKind::Call(contract_address))
    .seismic();  // Elements will be filled automatically

provider.send_transaction(tx.into()).await?;
```

### Manual Construction (Advanced)

```rust
use seismic_alloy_consensus::{TxSeismicElements, SeismicTransactionRequest};
use alloy::primitives::{B256, U96};

let keypair = TxSeismicElements::get_rand_encryption_keypair();
let nonce = TxSeismicElements::get_rand_encryption_nonce();

let elements = TxSeismicElements {
    encryption_pubkey: keypair.public_key(),
    encryption_nonce: nonce,
    message_version: 2,
    recent_block_hash: B256::from_slice(&latest_hash),
    expires_at_block: current_block + 100,
    signed_read: false,
};
```

## Notes

* **Auto-populated by fillers.** In normal usage, you never construct `TxSeismicElements` manually — the `SeismicElementsFiller` fills all fields from the network state.
* **Nonce uniqueness is critical.** Reusing an AES-GCM nonce with the same key breaks confidentiality. The random nonce generator provides sufficient entropy.
* **Part of AAD.** All fields in `TxSeismicElements` are included in the Additional Authenticated Data for AES-GCM, binding the ciphertext to these parameters.
* **RLP-encoded.** Elements are included in the RLP encoding of `TxSeismic` for hashing and signing.

## See Also

* [TxSeismic](/clients/alloy/transaction-types/tx-seismic.md) — Parent struct containing `TxSeismicElements`
* [TxSeismicMetadata](/clients/alloy/transaction-types/tx-seismic-metadata.md) — Uses elements for AAD construction
* [Encryption](/clients/alloy/provider/encryption.md) — Full encryption pipeline documentation
* [Shielded Calls](/clients/alloy/contract-interaction/shielded-calls.md) — How encryption is used in practice


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.seismic.systems/clients/alloy/transaction-types/tx-seismic-elements.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
