Tx Lifecycle
How a Seismic transaction is built, signed, submitted, validated, and executed. For the encryption primitives themselves (ECIES on secp256k1, KDF, AEAD, AAD binding), see Cryptography.
Building a Seismic transaction
A Seismic transaction is a legacy Ethereum tx with two additions: encrypted calldata in the data field, and a metadata struct called SeismicElements. The tx type is 74 / 0x4a.
SeismicElements consists of six Seismic-specific fields:
encryption_pubkey— the client's encryption pubkey for this tx (see Cryptography → Client keys for the available strategies)encryption_nonce— 12-byte AES-GCM noncerecentBlockHash— must be within 100 blocks of the latest blockexpires_at_block— block number after which the tx is invalidsigned_read— boolean (defaults totruein our client implementations); iftrue, restricts the tx to signed-read use only — see Signed readsmessage_version— integer controlling the signing format; see Wire vs. signing format
Combined with the standard Ethereum fields (sender, chain_id, nonce, to, value), the full 11-field bundle is TxSeismicMetadata, which is RLP-encoded and used as AAD when the AEAD seals the calldata (see Cryptography → Encryption scheme). Definitions in seismic-alloy-consensus.
The encrypted calldata is placed in the standard data / input field of the tx envelope.
Wire vs. signing format
A Seismic transaction has the same wire format in every case: an RLP-encoded type-0x4a envelope containing the tx fields, the encrypted calldata, and a signature. What can differ is the signing format — the bytes the ECDSA signature actually covers. This is controlled by the message_version field in SeismicElements:
message_version = 0— Standard. Signature covers the RLP-encoded preimage of the tx (same shape as other Ethereum typed txs, e.g. EIP-2930, EIP-1559). The validator re-RLP-encodes the preimage and recovers the signer from the signature.message_version = 2— EIP-712 typed-data form. Signature covers an EIP-712 hash of the tx as a structured-data message. This is what makes Seismic txs signable by MetaMask and other browser-extension wallets, which don't natively understand tx type0x4abut do supporteth_signTypedData. The validator reconstructs the typed-data hash and recovers the signer accordingly.message_version = 1— Reserved (originally planned foreth_personalSign-style signing; not implemented).
The wire-level type byte is always 0x4a; only how the signer was authenticated differs.
Submission and validation
Send to eth_sendRawTransaction like any Ethereum tx. Tx-pool validation rejects:
Txs of type
0x4awith incomplete or malformedSeismicElementsTxs not marked
0x4abut containingSeismicElementsTxs with
signed_read = true(those are foreth_call, not write txs)Calldata that fails to decrypt (see below)
Validated txs land in the pool and are included in blocks as usual.
Node-side decryption
For each Seismic tx in the pool, the validator:
Decodes the tx and recovers the signer (using the
message_version-appropriate signing format)Assembles the metadata, RLP-encodes it — this is the AAD
Derives the AES key from
tx_io_skand the client'sencryption_pubkeyvia ECDH + HKDF (see Cryptography)AEAD-opens the ciphertext with the derived key, the
encryption_nonce, and the AAD
On decryption failure, the tx is removed from the pool. On success, the plaintext calldata is passed to revm for execution inside the validator.
eth_getTransactionByHash returns the on-chain ciphertext form, not the plaintext. Clients that want to view their own historical calldata must arrange this client-side — see Cryptography → Client keys for the available strategies.
Read variant
For authenticated reads — eth_call requests that prove msg.sender identity to a contract — Seismic uses signed reads: the same Seismic tx protocol, sent to eth_call instead of eth_sendRawTransaction. See Signed Reads for the specifics.
Other notes
Seismic txs use the same gas parameters as legacy txs:
gasPriceandgasLimitSeismic txs cannot deploy bytecode. They must be sent to a specific address;
CREATE/CREATE2from a Seismic tx is rejected. This simplifies metadata validation, and there's no useful reason to deploy encrypted bytecodeCalldata encoding subtlety: shielded types (
suint,sbool, etc.) are encoded the same way as their public analogues. Solidity has no idea whether a function is called with a Seismic tx or a plain tx — so it's legal (though usually wrong) to alter shielded state via a plain tx, or to alter public state via a Seismic tx. Be deliberate about which kind of tx your contract accepts
Last updated

