# Igneum protocol specification, section 7: execution Spec version 0.1, 3 October 2026. Status of this section: Designed. Nothing here is implemented or measured. This section is the normative extract of `docs/design/execution-layer.md` (design version 0.1), which holds the reasons, the rejected alternatives and the precedents for every rule below. Where the two disagree, this section is wrong and the design document's decision table is right until the next MAJOR step (section 0.4). The rest of the execution layer (the transaction model, the two gas dimensions and the pgas table, proof records, the proving interface, the native proving precompile, the RPC surface) stays in the design document for 0.1. Terms. A chain block is a block on the selected chain. The segment of chain block C is C's mergeset in GHOSTDAG order, with C last; the executor runs segments in selected-chain order (design document, section 1.2). A segment is executed natively by every node, proven by miners in shards, and locked by the finality rule of section 3 independently of its proof. ## 7.1 EVM semantics Decided 3 October 2026 (ledger P5, closed by this section). Igneum runs Ethereum bytecode. Contracts see the environment of the chain block C whose segment is executing. The table is normative; a conforming executor MUST return these values. Ported contracts get this table as the documented differences; "unchanged" is not claimed. | Opcode or field | Igneum value | Ethereum value | Note for ported contracts | |---|---|---|---| | `block.number` (NUMBER) | The selected-chain height of C: genesis 0, each chain block +1, contiguous | Block height | About one per second at launch but not fixed; use timestamps for time. Blue score and DAA score are readable from the system contract `IgneumInfo` | | `block.timestamp` (TIMESTAMP) | `ts(C) = max(ts(parent chain block), C.timestamp_ms div 1000)` | Header timestamp, strictly increasing | Non-decreasing by rule; equal values happen at one block a second. The header timestamp alone may step backwards within Kaspa's tolerance (above the past median of a 27-sample window, below now plus 132 s), so the executor MUST apply the max rule and MUST NOT use the raw header value | | `blockhash(n)` (BLOCKHASH) | The hash of chain block n for `number - 256 <= n < number`, else 0 | Same | Hashes of merged non-chain blocks are not reachable from the EVM; `IgneumInfo` exposes the mergeset of a chain block | | `block.prevrandao` (PREVRANDAO, and DIFFICULTY) | `keccak256(epoch_seed ‖ number)`, where `epoch_seed` is the 10-minute class-group VDF output for the epoch that contains C (section 4) | RANDAO mix | Unbiasable by the producer. Predictable for the whole epoch (about 1 h) by anyone who has evaluated the VDF, so it is fine for a shuffle revealed later and wrong for a per-block lottery; adversarial randomness goes through the proving precompile with a committed input | | `block.coinbase` (COINBASE) | The `miner` address of the block that first included the executing copy of the transaction (design document, section 1.3) | Fee recipient | Also the address that receives the producer's part of the 80% tip share, so the correspondence Ethereum contracts assume holds. For a transaction in a red block it is the red block's miner, who is paid that share | | `block.gaslimit` (GASLIMIT) | The per-block execution gas limit `B_e`, a consensus constant | Header gas limit | A segment can hold up to the mergeset limit of blocks (180 at 1 BPS), so a segment's total can exceed `gaslimit` | | `block.basefee` (BASEFEE) | The execution base fee `f_e` at this segment | Same | The proving base fee `f_p` is readable from `IgneumInfo` | | `block.chainid` (CHAINID) | 4461 mainnet, 4462 public testnet, 4463 devnet | 1 | Registered on ethereum-lists/chains before the public testnet | | BLOBHASH, BLOBBASEFEE | Zero and 1 respectively; no blob transactions | EIP-4844 | As on L2s without blobs | | Opcode set | Cancun (PUSH0, TSTORE, TLOAD, MCOPY, SELFDESTRUCT per EIP-6780) | Cancun or later | EIP-7702 and the Prague BLS precompiles are deferred to phase two | | Precompiles | 0x01 to 0x09 (ecrecover, sha256, ripemd160, identity, modexp, ecadd, ecmul, ecpairing, blake2f); 0x0a absent and returns failure | Cancun has 0x0a | Heavy precompiles cost more here because proving gas is charged | The timestamp rule in words: the EVM clock never runs backwards, and it never runs ahead of the header clock. Under a burst of back-dated headers inside the 132-s tolerance the EVM clock holds still rather than stepping back; its drift from wall-clock under that attack is the devnet measurement R9 of the design document. Quoted gas price. Every transaction is metered in execution gas and in proving gas and charged `gas_used x (f_e + tip) + pgas_used x f_p` wei against the signed budget `gas_limit x max_fee_per_gas` (design document, section 4.1). Wallets sign one gas limit and one price, so the node folds the second dimension into the quote: `eth_gasPrice` returns `f_e + f_p x (pgas_est / gas_est) + tip` and `eth_estimateGas` returns a gas limit that covers both charges at that quote. A transaction heavy in pairing or modexp sees a higher quoted price than on Ethereum. Rationale and the rejected second-limit transaction type: design document, section 4.1. Rationale for every row, the precedents (Conflux eSpace, Kasplex, Igra) and the rejected blue-score alternative for `block.number`: design document, section 3. ## 7.2 Shard assignment Decided 3 October 2026 (ledger P8 and C9, closed by this section). Every segment is cut into shards by proving gas at transaction boundaries, deterministically from the native trace, so every node computes the same shard list and the same shard ids `(segment hash, shard index)` (design document, section 5.1). Shards are not claimed first-come. They are assigned by sortition: 1. **Eligible provers.** The vote keys above dust under section 3 (at least 100 blue blocks in the trailing 30-day window at the chain block that heads the segment). The finality-rule population is the proving population; there is no separate registration. 2. **Sortition, by weight.** Rule of 3 October 2026 (ledger F17, round 3); the earlier per-key ranking is withdrawn because keys are free (section 3.1 W6) and a miner who split its blocks over many keys held most of the tickets. The window is the list of blue blocks in the chain block's past that W2 of section 3.1 counts at that chain block, in GHOSTDAG order, restricted to blocks whose key is eligible under step 1; N is its length. For draw n = 1, 2, ..., `r_n = H("igneum-shard/" ‖ epoch_seed ‖ shard_id ‖ n) mod N`, H the chain's hash of section 0.6 read as an unsigned integer, and the key named by block `r_n` of the window is an assignee. A key drawn again holds one slot and the draw continues; the draw stops at 8 distinct keys, or earlier when every eligible key holds a slot. A key is drawn in proportion to its blocks in the window, which is its weight up to the bucket normalisation of W2, so splitting one key into a thousand changes nothing, as it changes nothing for the vote. `epoch_seed` is the VDF output of section 4 for the epoch containing the chain block, so the producer cannot bias it, and `shard_id` commits to the segment, so the assignment is keyed to the block and known to every node the moment the segment is executed. The function is public and deterministic: it needs no private key and no proof of evaluation. Whether to replace the hash draw with the private VRF of section 3.4 (so assignees are hidden until they prove) is settled together with O-3.5; nothing else in this section depends on the choice. 3. **Exclusive window.** From the moment the segment is executed, the 8 assignees hold the shard for 10 s of DAA time. A valid proof of the shard by any of the 8 that is included in a block during the window earns the shard's part of the proving pool (section 5.3); a proof by anyone else is valid but unpaid. 4. **Open claiming.** After the window any prover MAY prove the shard, and the first valid proof included in a block earns the shard's part of the pool. There is no claim and no shard bond: nothing waits on an assigned prover, so there is nothing to bond against (ledger P9). The bond remains in the external job market, where a customer does wait (section 5.4). 5. **Inclusion.** Shard proofs gossip like votes and any block producer MAY include them (design document, section 5.4). A block is invalid if a proof record it carries fails verification, names a chain block that is not on the carrying block's own selected-parent chain, or carries a post-root or receipts that differ from the execution of that segment along that chain (rule of 3 October 2026, ledger P11, round 3). The test is relative to the carrying block's own chain, never to the validating node's current selected chain: that chain is a property of the node's virtual and differs between honest nodes every second on a DAG, so a rule written against it makes two honest nodes disagree on one block. Written this way, validity is a function of the block and its past and every node computes it identically, as for every other rule in the fork. The design document's section 5.5 wording ("the node's selected chain") is superseded by this item. What the rule gives. A datacentre cannot sweep every shard by latency, because for 10 s only 8 drawn provers are paid, and the draw is proportional to a prover's blocks in the window, which is its 30-day mining however many keys it spreads them over. Income from the pool is bounded by the shards a prover is assigned plus the shards nobody assigned proves in time, not by how many it can grab. A segment producer could grind transaction content to move the assignment; it gains only if it is also one of the many eligible provers, and the draw of 8 out of the whole population makes the gain small. Its size is part of the measurement below. Parameters 8 and 10 s are Designed. They are set on the phase 4 devnet from the shard-time distribution across three prover speeds, with the acceptance test that the fastest prover wins under 25% of shards (design document, R7; O-5.1), and the test that one key and 1,000 keys of equal weight win the same number of shards (ledger F17). ## 7.3 Bridges Decided 3 October 2026 (ledger E7, closed by this section). 1. There are no bridged stablecoins at genesis. No USDC, USDT or other bridged asset is a launch feature, and the project does not request, label or seed a canonical bridged version of any asset before a proof bridge exists. 2. No bridge is called official. Igneum ships no bridge contract at genesis and endorses none. Anyone MAY deploy a bridge on Igneum, at their own risk and their users', and it is labelled by whoever runs it, never by the protocol or the project. 3. The proof bridge arrives with the consensus proof. A bridge contract on another chain that verifies Igneum state without a committee needs to verify a lock certificate, which means knowing the voter set and weights; that is the consensus proof of the design document, section 7, scoped as phase two. When it exists, the segment proof carries a self-verifying certificate and a bridge on Ethereum needs no relayer and no multisig. Until it exists, a light client is given a recent certificate and the key set out of band (ledger P4). 4. Settlement of the external job market in IGN, with its 10% burn, starts when the proof bridge lets Igneum see the payment (section 5.4). At launch customers pay on their own chain. Nothing in consensus changes for any of this: the segment claim already commits to the chain block hash, which is what the consensus proof folds in. ## 7.4 Parameters in this section | Parameter | Value | Label | |---|---|---| | Chain id | 4461 / 4462 / 4463 (mainnet / testnet / devnet) | Designed | | BLOCKHASH reach | 256 chain blocks | Designed (Ethereum's) | | PREVRANDAO source | 10-minute epoch VDF output, keccak256 with the chain height | Designed | | Opcode set, precompiles | Cancun; 0x01 to 0x09 | Designed | | Provers assigned per shard | 8 | Designed, set at the phase 4 devnet (O-5.1) | | Exclusive proving window | 10 DAA s | Designed, set at the phase 4 devnet (O-5.1) | | Shard claim bond | none | Designed | | Sortition draw | by weight: blue blocks drawn uniformly from the window, their keys assigned | Decided 3 October 2026 (ledger F17) | | Proof-record validity | relative to the carrying block's own selected-parent chain | Decided 3 October 2026 (ledger P11) | | Bridged stablecoins at genesis | none | Decided (3 October 2026) | | Official bridge | none | Decided (3 October 2026) | | Per-transaction pgas cap | the including block's remaining `B_p`, metered incrementally, halt before the crossing opcode or precompile | Decided 4 October 2026 (ledger P19), 7.5 | | Over-cap transaction | executed as out of gas: charged for gas and pgas consumed to the abort, status 0, nonce advanced, never skipped | Decided 4 October 2026 (ledger P19), 7.5 | | Mempool bounds | `gas_limit <= B_e`; estimated pgas `<= B_p`; template packs by the estimate | Designed, node policy (ledger P18, P19), 7.5 | ## 7.5 Proving gas per transaction: the cap and the abort Decided 4 October 2026 (ledger P18 and P19, closed by this section; `docs/bench-log.md`, "execution layer attack fixes"). Implemented on branch `execution-layer` and measured there. This section supersedes the execution-time skip of design 4.3 for a transaction's own running pgas: a transaction is never skipped for its proving cost after it has run, because a skip is free and the attack of P19 is exactly a transaction that runs for free. The intrinsic-only skip of design 1.5 (a copy whose intrinsic pgas alone does not fit the block) stays: it costs one comparison and no execution. 1. **Incremental metering under a cap.** The executor meters pgas opcode by opcode and precompile by precompile while the native execution runs. Before an opcode executes, or a precompile is entered, its pgas is added to the transaction's running total. If the total would exceed the cap, the opcode or precompile does not run and the transaction halts there. The cap is the including block's remaining proving budget: `B_p` minus the pgas already charged to the block, which includes the intrinsic pgas of every copy included before it and of the transaction itself. A transaction carries no pgas limit field of its own (7.1, design 4.1); its own limit is the signed wei budget, which halts it as out of gas under 7.1 the moment the running charge would cross it, so the binding limit is whichever of the two comes first. A halt propagates: every frame still open halts at its next instruction, so a contract cannot catch the failed call and go on. The native work of one transaction is therefore bounded by `B_p` of proving gas and its own gas limit of execution gas, whatever its input, and no block ever carries more than `B_p`. 2. **An aborted transaction pays, and its nonce advances.** It is not skipped. It is an executed transaction with status 0, no logs and its state changes reverted, as a transaction that ran out of gas; its nonce advances. The sender pays `gas_consumed x (f_e + tip) + pgas_consumed x f_p`: `gas_consumed` is the execution gas spent up to the abort, intrinsic included and never the whole limit; `pgas_consumed` is the pgas metered up to the abort plus the intrinsic pgas. The proving part never takes the charge past the signed budget. Both base fees burn and the tip splits as design 4.4. The receipt carries `pgasAborted: true`. A later copy of the same transaction is skipped by the nonce rule of design 1.3 at one account read, so it is never executed twice, and the sender's later nonces are not held behind it. 3. **Admission and the template.** A node's mempool does not admit a transaction whose `gas_limit` exceeds `B_e`, nor one whose estimated pgas exceeds `B_p`; the estimate is a simulation at the tip under the cap of item 1, so it costs at most `B_p` of pgas, and the rejection names the pgas metered and `B_p`. The template builder packs by that estimate: it never includes a transaction whose estimated pgas exceeds the block's remaining `B_p`, and it stops at the first transaction that does not fit a budget, so a sender's later nonces never jump ahead. These are node policy (design 1.4), not consensus; item 1 is the consensus rule and holds whatever a miner includes. 4. **The pgas dimension is visible.** `eth_estimateGas` folds the proving charge into the quoted gas limit (7.1) and fails, naming the pgas metered and `B_p`, for a call that hits the cap; `eth_call` fails the same way. `igneum_estimateGas` returns both dimensions for the same simulation: `gasUsed`, `pgas`, the folded `gas`, `provingGasLimit`, both base fees and `exceedsProvingLimit`, so a wallet or tool can show the proving side. What the rule gives, measured (bench-log, 4 October 2026, `B_p` 30 M, modexp loop of 9,000 calls): before, 10.85 ms of native execution per inclusion, nothing charged, the nonce stuck and the sender's later transactions never includable; after, the mempool refuses it, a hostile miner's inclusion is cut at 29,998,593 pgas after 4,680,437 gas in 11.4 ms, the sender pays 0.0394 IGN, the nonce advances, a second inclusion is skipped in 35 us, and the next nonce executes in the following blocks.