diff --git a/src/pages/protocol/blockspace/overview.mdx b/src/pages/protocol/blockspace/overview.mdx index 69ff4771..12c8ecbc 100644 --- a/src/pages/protocol/blockspace/overview.mdx +++ b/src/pages/protocol/blockspace/overview.mdx @@ -1,5 +1,5 @@ --- -description: Technical specification for Tempo block structure including header fields, payment lanes, subblocks, and system transaction ordering. +description: Technical specification for Tempo block structure including header fields, payment lanes, and system transaction ordering. --- # Blockspace Overview @@ -10,7 +10,7 @@ This specification defines the structure of valid blocks in the Tempo blockchain ## Motivation -Tempo blocks extend the Ethereum block format in multiple ways: there are new header fields to account for payment lanes and sub-blocks, and system transactions are added to the block body for the fee AMM and other protocol operations. This specification contains all the modifications to the block format. +Tempo blocks extend the Ethereum block format in multiple ways: there are new header fields to account for payment lanes and shared gas accounting, and system transactions are added to the block body for the fee AMM and other protocol operations. This specification contains all the modifications to the block format. ## Specification @@ -25,7 +25,7 @@ pub struct Header { } ``` - `inner` is the canonical Ethereum header (parent_hash, state_root, gas_limit, etc.). -- `general_gas_limit` and `shared_gas_limit` carve up the canonical `gas_limit` for payment and sub-block gas (see [payment lane specification](/protocol/blockspace/payment-lane-specification) and [sub-block specification](/protocol/blockspace/sub-block-specification)). +- `general_gas_limit` and `shared_gas_limit` partition the canonical `gas_limit` for payment and non-payment capacity (see [payment lane specification](/protocol/blockspace/payment-lane-specification)). - `timestamp_millis_part` stores the sub‑second component; the full timestamp is `inner.timestamp * 1000 + timestamp_millis_part` . ### Block body @@ -33,12 +33,10 @@ The block body in Tempo retains the canonical Ethereum block body structure, wit 1. Start-of-block system transaction(s) (must begin with the rewards registry call). 2. Proposer lane transactions, subject to `general_gas_limit` on non-payment transactions. -3. Sub-block transactions, grouped by proposer and prefixed with the reserved nonce key. -4. Gas incentive transactions that consume leftover shared gas. -5. End-of-block system transactions (see below). +3. Remaining transactions that consume the shared gas budget. +4. Protocol-defined end-of-block system transactions, when required. ### System transactions -A valid tempo block must contain the following system transactions: +A valid tempo block must contain the following system transaction: - **Rewards Registry (start-of-block)** — must be the first transaction in the block body; refreshes validator rewards metadata before user transactions begin. Detailed specification [here](/protocol/tip20-rewards/spec). - - **Subblock Metadata (end-of-block)** — contains metadata about the sub-blocks included in the block. Detailed specification [here](/protocol/blockspace/sub-block-specification). diff --git a/src/pages/protocol/blockspace/payment-lane-specification.mdx b/src/pages/protocol/blockspace/payment-lane-specification.mdx index 0f1e9a0c..c6340181 100644 --- a/src/pages/protocol/blockspace/payment-lane-specification.mdx +++ b/src/pages/protocol/blockspace/payment-lane-specification.mdx @@ -6,7 +6,7 @@ description: Technical specification for Tempo payment lanes ensuring dedicated ## Abstract -This specification introduces a second consensus gas constraint for **non-payment** transactions. Transactions are classified as either payments or non-payments based solely on their transaction data, without requiring any access to blockchain state. For a block to be valid, total `gas_used` by the block must be less than the `gas_limit`. Non-payment transactions executed in the proposer's lane (i.e. before the gas incentive section) must consume at most `general_gas_limit`, a new field added to the header. Once that budget is exhausted, any additional inclusion must come via the gas incentive lane defined in the [sub-blocks specification](/protocol/blockspace/sub-block-specification). +This specification introduces a second consensus gas constraint for **non-payment** transactions. Transactions are classified as either payments or non-payments based solely on their transaction data, without requiring any access to blockchain state. For a block to be valid, total `gas_used` by the block must be less than the `gas_limit`. Non-payment transactions executed in the proposer's lane (i.e. before the gas incentive section) must consume at most `general_gas_limit`, a new field added to the header. Once that budget is exhausted, additional inclusion is constrained by the remaining shared gas budget. ## Motivation @@ -52,4 +52,3 @@ for all i such that !is_payment(tx[i]) and tx[i] is in the proposer's lane ``` Where `gas_consumed` includes intrinsic gas and gas burned by reverts, as in the existing protocol. - diff --git a/src/pages/protocol/blockspace/sub-block-specification.mdx b/src/pages/protocol/blockspace/sub-block-specification.mdx deleted file mode 100644 index 3a2a00d8..00000000 --- a/src/pages/protocol/blockspace/sub-block-specification.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -description: Technical specification for subblocks enabling non-proposing validators to include transactions in every block with guaranteed blockspace access. ---- - -# Sub-block Specification - -## Abstract - -This proposal allows non-proposing validators to propose a limited set of transactions in each block through signed **sub-blocks**. Sub-blocks are sent directly to the main proposer and their transactions are included in the block as described below. Consensus does not enforce inclusion. The proposer is incentivized to include sub-blocks by provisioning additional gas upon sub-block inclusion, which permits them to include additional transactions at the bottom of the block as described below. - -## Motivation - -In traditional blockchains, only the current block proposer can include transactions. This means validators must wait for their scheduled slot to provide fast inclusion for their users. Tempo changes this by letting **all validators** contribute transactions to every block through sub-blocks. - -For validators, this is good as they no longer have to wait for their turn as proposer to provide low-latency inclusion for their users. They have guaranteed access to blockspace in every block, allowing them to include transactions whenever needed. Validators can also ensure a specific transaction execution order within their sub-block, giving them controlled ordering of their transactions. - -For users, this is good because transactions can be included faster since they can go through any validator, not just the current proposer. Access to blockspace becomes more predictable as it is smoothed across all validators rather than being concentrated with a single proposer. Time-sensitive transactions benefit from lower latency and can be included more quickly. - -This proposal smooths access to blockspace across validators. It enables every validator to provide low-latency inclusion for themselves, their users, or their partners, without waiting for their turn as proposer. - -## Specification - -This specification describes the process in temporal order. - -### 0. Definitions - - * The gas limit of the whole block is `G`. There are `n` validators: 1 proposer and `n-1` other non-proposers. - * `f` fraction of the gas limit of the block, `0 < f < 1` is reserved for the main proposer. - -### 1. Sub-blocks - - * Each validator can construct a sub-block. Sub-blocks follow this structure: -``` -sub-block = rlp([version, parent_hash, fee_recipient, [transactions], signature]) -``` -where: -* `version = 1`, -* `parent_hash` is the parent hash of the previous block. -* `fee_recipient` is the EOA at which this validator wants to receive the fees included in this block. -* `[transactions]` is an ordered list of transactions. Transactions in a sub-block must satisfy additional conditions described below in [Section 1.1](#11-sub-block-transactions). We explicitly allow for this list to be empty: a validator with no transactions to propose may still send a sub-block so that the proposer gets extra gas for the gas incentive region, described below. -* The `signature` field is the validator signing over a hash computed as -`keccak256(magic_byte || rlp([version, parent_hash, fee_recipient, [transactions]]))`, -where `magic_byte = 0x78`, The signature ensures that this sub-block is valid only for the declared slot, and that the proposer cannot alter the order or set of transactions included in a sub-block. -* The validator sends this sub-block directly to the next proposer. - - -For each validator `i`, define - - `unreservedGas[i] = (1 - f) * G / n - Σ(gasLimit of transactions in sub-block[i])` - -#### 1.1 Sub-block Transactions - -We use the two-dimensional nonce sequence to simplify transaction validity. In this construction, the nonce_key is a `u256` value. - -Let `validatorPubKey` be the public key of the validator proposing a given sub-block. Let `validatorPubKey120` be the most significant 120 bits of the validator's public key. - -We reserve sequence keys to each validator by requiring that the first (most significant) byte of the `sequence key` is the constant byte `0x5b`, and the next 15 bytes (120 bits) encode `validatorPubKey120`. - -Formally, we require that: - -1. The `sequence key` of any transaction in the sub-block is of the form `(0x5b << 248) + (validatorPubKey120 << 128) + x`, where `x` is a value between `0` and `2**128 - 1`. In other words, the most significant byte of the sequence key is always `0x5b`, the next 15 bytes are the most significant 120 bits of the validator's public key, and the final 32 bytes (128 bits) still allow for 2D-nonces. - -2. No two validators share the same `validatorPubKey120`; each validator's reserved space is distinct. - -This explicit prefixing with `0x5b` ensures the reserved sequence key space is unambiguous and disjoint across validators. Sub-block proposers control all sequence keys of the form above, and can ensure that nonces are sequential within their space. - -:::note[Reserved Nonce Space] -To prevent transaction conflicts, each validator has a reserved nonce space. Transactions in sub-blocks use special nonce sequence keys that identify which validator proposed them. This ensures that validators can't interfere with each other's transactions. -::: - -Further, we require that sub-block transactions are signed solely by the root EOA key of the address sending the transaction. - -### 2. Block Construction - -The proposer collects sub-blocks from other validators. It now constructs a block with the following contents: - -``` -transactions = [list of own transactions] | [sub-block transactions] | [gas incentive transactions] -``` - - * `list of own transactions` are regular transactions from the proposer with `f * G` gas limit. - * `sub-block transactions` are transactions from the included sub-blocks. **This includes a sub-block from the proposer itself if the proposer desires.** Nonce sequence keys with prefix `0x5b` should only appear in this section. - * `gas incentive transactions` are additional transactions that the proposer can include after the sub-block transactions, with additional gas defined below. - -We have the following new **header field**: -``` -shared_gas_limit // The total gas limit allocated for the sub-blocks and gas incentive transactions -``` - -#### 2.1 System transaction - -The block includes a **new system transaction**, whose call data contains, for each included sub-block, the public key of the validator proposing, the `feeRecipient` for that sub-block and the signature of the sub-block. It is a no-op, and is there for execution layer blocks to be self-contained/carry all context. - -| Field | Value / Requirement | Notes / Validation | -|--------------------------------------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------| -| **Type** | Legacy transaction | | -| **Position in Block** | **Last transaction** | Block is **invalid** if absent. | -| **From (sender)** | `0x0000000000000000000000000000000000000000` | Zero address | -| **To (recipient)** | `0x0000000000000000000000000000000000000000` | No-op | -| **Calldata** | `rlp([[version, validator_pubkey, fee_recipient, signature], ...])` | Sub-block version (currently = 1), each included sub-block's validator public key, fee_recipient, and signature. | -| **Value** | `0` | No native token transfer. | -| **Nonce** | 0 | | -| **Gas Limit** | 0 | Does **not** contribute to block gas accounting. | -| **Gas Price** | 0 | Independent of block base fee; does not pay fees. | -| **Signature** | `r = 0`, `s = 0`, `yParity = false` | Empty signature designates system transaction. | - -### 3. Proposer Behavior - -* Construct Main Block in the usual way. -* Collect sub-blocks from validators, including from self. Verify signatures and gas bounds of sub-blocks. Skip (i.e., do not include) invalid or missing sub-blocks; include valid ones. Transactions from a sub-block must be contiguous in the block, but sub-blocks can be included in any order. -* Compute proposer Gas Incentive section limit: - ``` - gasIncentiveLimit = Σ(unreservedGas[i]) for all included sub-blocks [i] - ``` -* Append transactions at the bottom up to this gas limit. -* Construct and include the [system transaction](#21-system-transaction) at the bottom of the block. - - -#### 3.1 Proposer Incentives - - * We do not enforce censorship-resistance for the transactions at consensus layer. - * Proposer is incentivized by additional gas from sub-blocks included and reciprocity. - * Additional gas is unrestricted so it could include backruns etc from sub-block transactions. - -### 4. Block Validity Rules: -We can now define what a valid block is: - 1. Gas Limits: - * `[list of own transactions]` uses gas at most `f * G`. - * `[sub-block transactions]`: the sum of `gas_limits` of all transactions in each sub-block is lower than the per-sub block gas limit: `Σ(gasLimit of transactions in sub-block[i]) <= (1-f) * G / n`. - * `[gas incentive transactions]` use total gas `<= gasIncentiveLimit`. - * General transactions gas limit from payments lane spec applies to `[list of own transactions]`. - 2. Transactions with nonce sequence key prefix `0x5b` appear only in the `[sub-block transactions]`. Transactions are contiguous by validator. - The `[list of own transactions]` and `[gas incentive transactions]` can use any un-reserved `sequence key`. - 3. [System transaction](#21-system-transaction) is present, in the correct position, and valid (matches contents of the block). - 4. Transactions in the main proposers's section and the gas incentive section are valid in the standard way (signature, nonce, can pay fees). - -#### 4.1 Failures for Sub-block Transactions - -Even if a transaction can pay its fees when the sub-block is created (i.e., when the sub-block is sent to the proposer), it may not be able to pay its fees when the sub-block is included and the block is processed. Here is a list of possible scenarios: - -* **Fee Failure Scenarios**: -- The Fee AMM liquidity for the user's `fee_token` is insufficient (e.g., it was used up by previous transactions in the block). -- The user's balance of the `fee_token` is insufficient (e.g., the user spent that balance in previous transactions in the block). -- The user or validator changed their `fee_token` preference in the block and the transaction cannot pay its fees because of the new preference. - -In all these scenarios, transaction is considered valid, increments the nonce, skips fee payment and execution, and results in an exceptional halt. - -### 5. Transaction Fee Accounting - -The fee manager is updated to handle fee accounting across sub-blocks: -- For the main proposer transactions, fees are paid to the main proposer's `fee_recipient` as usual. -- For the sub-block transactions, fees are paid to the `fee_recipient` of the sub-block (available from the system transaction). -- For the gas incentive transactions, fees are paid to the proposer's `fee_recipient`. - -In all cases, the fee is paid in the preferred `fee_token` of the `fee_recipient`, using liquidity from the fee AMM as necessary (i.e., `validatorTokens[fee_recipient]` from the FeeManager contract). If the `fee_recipient` has not set a preferred `fee_token`, then we use pathUSD as a fallback. - - diff --git a/src/pages/protocol/index.mdx b/src/pages/protocol/index.mdx index 2cb4a082..fff835a9 100644 --- a/src/pages/protocol/index.mdx +++ b/src/pages/protocol/index.mdx @@ -44,7 +44,7 @@ This section provides details on the Tempo Protocol specifications, and serves a title="Tempo Transactions" /> uint64)` - 2D nonce tracking @@ -1128,4 +1128,3 @@ The introduction of 7702 delegated accounts already created complex cross-transa Because a single transaction can invalidate multiple others by spending balances of multiple accounts **Assessment:** While this transaction type introduces additional pre-execution validation costs, all costs are bounded to reasonable limits. The mempool complexity issues around cross-transaction dependencies already exist in Ethereum due to 7702 and accounts with code, making static validation inherently difficult. So the incremental cost from this transaction type is acceptable given these existing constraints. - diff --git a/vocs.config.ts b/vocs.config.ts index c806ef91..aeaa9afe 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -461,10 +461,6 @@ export default defineConfig({ text: 'Payment Lane Specification', link: '/protocol/blockspace/payment-lane-specification', }, - { - text: 'Sub-block Specification', - link: '/protocol/blockspace/sub-block-specification', - }, { text: 'Consensus and Finality', link: '/protocol/blockspace/consensus', @@ -785,10 +781,6 @@ export default defineConfig({ source: '/documentation/protocol/:path*', destination: '/protocol/:path*', }, - { - source: '/errors/tx/SubblockNonceKey', - destination: '/protocol/blockspace/sub-block-specification#4-block-validity-rules', - }, { source: '/stablecoin-exchange/:path*', destination: '/stablecoin-dex/:path*',