Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/dev/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ Mini-blocks are intentionally compact and do not include the same metadata field

Yes.
Preconfirmation of mini-blocks by the sequencer has the same level of guarantees as that of EVM blocks.
Every mini-block header is [signed by the sequencer](../mini-block.md#sequencer-signatures), so the preconfirmation is cryptographically verifiable.

### Does the performance dashboard (uptime.megaeth.com) display the block height in mini-blocks or EVM blocks?

Expand Down
1 change: 1 addition & 0 deletions docs/dev/read/realtime-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Use `latest` or `pending` as the block tag and you get mini-block-level freshnes

Mini-blocks carry the same preconfirmation guarantee as EVM blocks.
The sequencer treats them identically — results returned by the Realtime API are not "tentative" or "unconfirmed."
Each mini-block header is signed by the sequencer, making the commitment independently verifiable — see [Sequencer signatures](../../mini-block.md#sequencer-signatures).

### Example: real-time balance query

Expand Down
23 changes: 13 additions & 10 deletions docs/dev/read/rpc/eth_subscribe.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,19 @@ Streams mini-blocks as they are produced by the sequencer.

**Notification schema:**

| Field | Type | Notes |
| ---------------------- | --------------- | -------------------------------------------------------- |
| `block_number` | `Quantity` | EVM block number that this mini-block belongs to |
| `block_timestamp` | `Quantity` | EVM block timestamp |
| `index` | `Quantity` | Index of this mini-block within the EVM block |
| `mini_block_number` | `Quantity` | Global mini-block height |
| `mini_block_timestamp` | `Quantity` | Creation timestamp (Unix microseconds) |
| `gas_used` | `Quantity` | Gas consumed in this mini-block |
| `transactions` | `Transaction[]` | Transactions (same schema as `eth_getTransactionByHash`) |
| `receipts` | `Receipt[]` | Receipts (same schema as `eth_getTransactionReceipt`) |
| Field | Type | Notes |
| ---------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `block_number` | `Quantity` | EVM block number that this mini-block belongs to |
| `block_timestamp` | `Quantity` | EVM block timestamp |
| `index` | `Quantity` | Index of this mini-block within the EVM block |
| `mini_block_number` | `Quantity` | Global mini-block height |
| `mini_block_timestamp` | `Quantity` | Creation timestamp (Unix microseconds) |
| `gas_used` | `Quantity` | Gas consumed in this mini-block |
| `transactions` | `Transaction[]` | Transactions (same schema as `eth_getTransactionByHash`) |
| `receipts` | `Receipt[]` | Receipts (same schema as `eth_getTransactionReceipt`) |
| `transaction_root` | `Hash` | Merkle (MPT) root of `transactions` |
| `receipt_root` | `Hash` | Merkle (MPT) root of `receipts` |
| `signature` | `Object` | Sequencer's ECDSA signature over the header hash, as `r`, `s`, and `yParity` fields. Absent for pre-Rex5 mini-blocks. See [Sequencer signatures](../../../mini-block.md#sequencer-signatures) |

### `newHeads`

Expand Down
99 changes: 97 additions & 2 deletions docs/mini-block.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,111 @@ Mini-blocks share the core properties you would expect from any block:

- **Ordered.** Mini-blocks are totally ordered by height, starting from 0 at genesis.
- **Complete.** Every transaction processed by the sequencer appears in exactly one mini-block.
- **Preconfirmed.** A transaction included in a mini-block carries the same preconfirmation guarantee as one included in an EVM block — the sequencer has committed to its ordering and result.
- **Preconfirmed.** A transaction included in a mini-block carries the same preconfirmation guarantee as one included in an EVM block — the sequencer has committed to its ordering and result, and [signs every mini-block header](#sequencer-signatures) to make that commitment verifiable.

Where they differ from EVM blocks:

| Property | EVM Block | Mini-Block |
| ------------------------------ | ----------- | -------------------------------------------------------------------------------------------------------- |
| Production interval | ~1 second | ~10 milliseconds |
| Header size | ~500+ bytes | Compact (no Merkle roots, no bloom filter) |
| Header size | ~500+ bytes | Compact (no state root, no bloom filter) |
| Timestamp resolution | 1 second | Microsecond (via [High-Precision Timestamp](dev/execution/system-contracts.md#high-precision-timestamp)) |
| Compatible with standard tools | Yes | Requires [Realtime API](dev/read/realtime-api.md) |
| Contains state root | Yes | No |

## Sequencer signatures

The preconfirmation guarantee is not just a promise — it is cryptographically enforced.
The sequencer signs every mini-block header with its sequencer key, and the signature is delivered alongside the mini-block in the [Realtime API](dev/read/realtime-api.md) stream.
A signed mini-block is a binding commitment: if the sequencer ever sealed an EVM block that contradicts a mini-block it signed, anyone holding the signed header could prove the misbehavior.

The signing key is registered onchain in the [SequencerRegistry](https://docs.megaeth.com/spec/system-contracts/sequencer-registry) system contract at `0x6342000000000000000000000000000000000006`, introduced in Rex5.
The key can be rotated by scheduling a change in the registry; rotations take effect at an EVM block boundary, and the full change history remains queryable onchain.

The signature is a standard secp256k1 ECDSA signature over `keccak256(rlp(header))`, where the header is the following eight fields of the [`miniBlocks` subscription payload](dev/read/rpc/eth_subscribe.md#miniblocks), RLP-encoded in this order:

| # | Payload field | Type |
| --- | ---------------------- | ------------ |
| 1 | `block_number` | integer |
| 2 | `block_timestamp` | integer |
| 3 | `index` | integer |
| 4 | `mini_block_number` | integer |
| 5 | `mini_block_timestamp` | integer |
| 6 | `gas_used` | integer |
| 7 | `transaction_root` | 32-byte hash |
| 8 | `receipt_root` | 32-byte hash |

Integers are RLP-encoded in their minimal big-endian form.
The signature is verifiable onchain with `ecrecover`.
The `signature` field of the payload carries the components as an object: `r`, `s`, and `yParity`.

{% hint style="info" %}
Mini-blocks produced before Rex5 are unsigned — the `signature` field is absent from their payloads.
{% endhint %}

### Verifying a mini-block signature

To verify a mini-block, rebuild the header hash, recover the signer from the signature, and compare it against the sequencer key registered onchain.

The example below uses [viem](https://viem.sh) and takes a notification payload `mb` exactly as delivered by the [`miniBlocks` subscription](dev/read/rpc/eth_subscribe.md#miniblocks).

```typescript
import {
createPublicClient,
http,
keccak256,
toRlp,
recoverAddress,
parseAbi,
} from "viem";

const client = createPublicClient({
transport: http("https://mainnet.megaeth.com/rpc"),
});

// RLP integer form: minimal big-endian bytes; zero is the empty byte string
const int = (hex: `0x${string}`): `0x${string}` => {
let h = BigInt(hex).toString(16);
if (h === "0") return "0x";
return `0x${h.length % 2 ? "0" + h : h}`;
};

// `mb` is a notification payload from the `miniBlocks` subscription
async function isSignedBySequencer(mb: any): Promise<boolean> {
// 1. Rebuild the signed digest: keccak256(rlp(header))
const hash = keccak256(
toRlp([
int(mb.block_number),
int(mb.block_timestamp),
int(mb.index),
int(mb.mini_block_number),
int(mb.mini_block_timestamp),
int(mb.gas_used),
mb.transaction_root,
mb.receipt_root,
]),
);
// 2. Recover the signer from the raw digest (no EIP-191 prefix)
const signer = await recoverAddress({ hash, signature: mb.signature });
// 3. Look up the sequencer key that was active for this block
const sequencer = await client.readContract({
address: "0x6342000000000000000000000000000000000006",
abi: parseAbi(["function sequencerAt(uint256) view returns (address)"]),
functionName: "sequencerAt",
args: [BigInt(mb.block_number)],
});
return signer.toLowerCase() === sequencer.toLowerCase();
}
```

When verifying historical mini-blocks, use `sequencerAt(blockNumber)` rather than `currentSequencer()` — the sequencer key can rotate, and the registry resolves which key was active at any block.
`currentSequencer()` is sufficient when verifying live mini-blocks as they stream in.

{% hint style="warning" %}
A valid signature proves the sequencer committed to the mini-block's contents — it does not by itself prove finality.
Full finality still depends on the containing EVM block being posted to and finalized on the L1.
{% endhint %}

## Relationship to EVM Blocks

Every mini-block belongs to exactly one EVM block — its transactions never span multiple EVM blocks.
Expand Down Expand Up @@ -102,4 +195,6 @@ Each notification delivers the mini-block's transactions, receipts, and state ch

- [Architecture](architecture.md) — how transactions flow through the MegaETH network
- [Realtime API](dev/read/realtime-api.md) — subscribe to mini-blocks and get execution results with minimum latency
- [eth_subscribe](dev/read/rpc/eth_subscribe.md) — full reference of the `miniBlocks` subscription payload
- [High-Precision Timestamp](dev/execution/system-contracts.md#high-precision-timestamp) — microsecond timestamps available within mini-blocks
- [SequencerRegistry (spec)](https://docs.megaeth.com/spec/system-contracts/sequencer-registry) — onchain registry of the sequencer signing key
Loading