Gravity v1.7.3
Gravity v1.7.3
Release: v1.7.3
Full Changelog: v1.7.2...v1.7.3
Related pinned components:
- gravity-reth: rev
3fd603db— picks up three greth PRs since v1.7.2: #358 (audit-#712 pipe gas_limit + audit-#621 system-tx gas budget), #361 (hardfork stub cleanup), #362 (persist.merge-blockscatch-up)
This release ships Prague activation on mainnet (chain id 127001) plus two consensus-critical audit follow-ups on the pipe-execution gas_limit, and adds a binary-authoritative hardfork schedule so operator misconfig cannot silently disable an activated fork on gravity-owned chains.
Highlights
- Prague activated on mainnet. #766 sets
pragueTimeingenesis/mainnet/genesis.json, and #763 introducesGravityChainSpecParserwhich override-pinspragueTime = 1_782_709_200forGRAVITY_MAINNET_CHAIN_ID = 127001at parse time. Any operator-supplied genesis on that chain id is normalised to the governance-pinned value before EL or CL reads it, closing the misconfig path where a mismatchedpragueTime(orpragueTime = 0, which silently leaves HISTORY_STORAGE unallocated) would fork the network. - CRITICAL: consensus divergence on
pipe-block-gas-limit(greth#358, audit-#712). Blockgas_limitwas sourced from the per-node--gravity.pipe-block-gas-limitCLI flag, so validators with mismatched CLI values produced different block hashes from the sameOrderedBlock. Hardcoded to a single workspace constPIPE_BLOCK_GAS_LIMIT = 1_000_000_000; CLI flag, config field, and all init shims removed (mainnet pre-launch, no compat needed). - HIGH:
gas_used > gas_limitreachable under load (greth#358, audit-#621). System txns (metadata + DKG/JWK) executed before user-tx filtering, then had their gas appended to the block viaSystemTxnResult::insert_to_executed_ordered_block_result. Because the filter received the fullblock.gas_limitas budget, a saturating user block plus non-trivial system overhead could pushheader.gas_used > header.gas_limitin release builds (validate_execution_outputis debug-only). Fix: passsum_system_gas(exact, computed from already-executed system results) intocreate_block_for_executorand applyblock.gas_limit.saturating_sub(sum_system_gas)to the filter budget.block.header.gas_limititself stays stable so RPC / indexer semantics are unchanged. - Consensus startup hardening (audit follow-ups, #733). Four gravity-audit fixes rolled up:
BlockBufferManager::initvalidation returns errors instead of leaving the manager uninitialised; JWK/DKG validator-tx deserialization replacesunwrapwith guarded handling that drops malformed txns; epoch-change readiness synchronises with theBlockStateMachinemutex to close a release-before-consume window on ordered-block reads/writes; GCEI observability (Prometheus counters for filtered txns and coinbase-fallback paths). - from-genesis PFN catch-up speedup (greth#362, default off). New
gravity.persist.merge-blockscoalesces consecutive blocks into gas/state-bounded groups (MERGE_GROUP_MAX_GAS = 1e9,MERGE_GROUP_MAX_STATE = 1e6changed accounts) and commits each group with one fsync. Targets from-genesis PFN catch-up which is fsync-bound on the per-block path. Group is atomic (crash rolls back; stage checkpoints re-execute idempotently). Default-off path is byte-for-byte unchanged. - Randomness precompile e2e coverage (#751). Single-node coverage of the randomness-by-height precompile plus Solidity wrapper usage; single-node alpha hardfork config switched to
alphaTimefor the timestamp-gated reth change. - PFN transaction-lookup pruning (#752). New PFN prune reth config template selected when
prune_transactionlookup_distanceis set in node TOML; default PFN template behaviour unchanged when prune is not configured.
Breaking Changes
Chain id 127001 overrides pragueTime from the binary
For GRAVITY_MAINNET_CHAIN_ID = 127001, GravityChainSpecParser (bin/gravity_node/src/chainspec.rs) overrides pragueTime in Genesis to 1_782_709_200 before From<Genesis> for ChainSpec runs in greth. Operator-supplied pragueTime for that chain id is dropped. The override is applied at parse time so the constructed Arc<ChainSpec> — genesis_header, fork_id, fork_filter, the inner SealedHeader::hash OnceLock — is correct from t=0 with no post-construction mutation. The CL side (ConsensusHardforks::from_genesis_extra_fields) reads from the same post-override extra_fields, so EL and CL agree on the timestamp with no parallel CL table.
For any chain id not in the table the parser is a no-op and current genesis-driven behaviour is unchanged. alpha_time is currently None on 127001 (forward-defence): no timestamp has been chosen onchain yet, and any operator-supplied alphaTime on mainnet genesis is dropped until governance pins a value.
--gravity.pipe-block-gas-limit CLI flag removed
The per-node --gravity.pipe-block-gas-limit CLI flag / config field / init shims are removed in greth#358. The block gas_limit used by the pipe layer is now a single workspace const PIPE_BLOCK_GAS_LIMIT = 1_000_000_000. Any run scripts / systemd units passing this flag will fail to parse — remove the flag before deploying v1.7.3. block.header.gas_limit semantics on the RPC / indexer side are unchanged.
What's Changed
Genesis / Chainspec
- chore(genesis): enable Prague on mainnet by @Lchangliang in #766 — sets
pragueTime = 1_782_709_200ingenesis/mainnet/genesis.json. - feat(chainspec): binary-authoritative hardfork schedule for gravity chains by @nekomoto911 in #763
- Introduces
GravityChainSpecParserinbin/gravity_node/src/chainspec.rsthat wraps upstreamEthereumChainSpecParserand applies a compile-time override table to thealloy_genesis::Genesisvalue on the file / inline-JSON fallthrough path, beforeFrom<Genesis> for ChainSpecruns in greth. - Initial table on
127001:prague_time = Some(1_782_709_200)(governance-pinned togravity-mainnet-gitops/genesis.json) andalpha_time = None(forward-defence — dropped from operator-supplied genesis until governance picks a value). - Named chains (
mainnet/sepolia/holesky/hoodi/dev) delegate to upstream unchanged. - Maintenance rule: adding or modifying an entry for a shipped chain id is a consensus change; existing entries must never be removed;
None → Some(ts)is the only allowed transition.
- Introduces
Bug Fixes — Consensus (audit follow-ups)
- fix(consensus): harden startup and block buffer handling by @Lchangliang in #733
- gravity-audit#31:
BlockBufferManager::initvalidation returns errors instead of leaving the manager uninitialised after an early return. - gravity-audit#516: JWK/DKG deserialization on validator txns replaces
unwrapwith guarded handling; malformed validator txns are dropped instead of panicking the node. - gravity-audit#522: synchronises epoch-change readiness with the
BlockStateMachinemutex, closing a release-before-consume window on ordered-block reads/writes. - gravity-audit#598: Prometheus counters for GCEI filtered transactions and coinbase-fallback paths.
- gravity-audit#31:
Features
- feat(cluster): support PFN transaction lookup pruning by @Lchangliang in #752
- New PFN prune reth config template selected when
prune_transactionlookup_distanceis set in node TOML; default PFN template behaviour unchanged when prune is not configured. - Render-checked: PFN deploy with
prune_transactionlookup_distanceemits--full --prune.transactionlookup.distance=10064; default config keeps--devand no prune args. - Local faucet init works on macOS without GNU
timeout;pfn_chaintest collects on Python 3.9 (postponed annotations import).
- New PFN prune reth config template selected when
Tests
- test(e2e): add randomness e2e coverage by @Lchangliang in #751
- Adds single-node coverage of the randomness-by-height precompile plus Solidity wrapper usage.
- Switches the single-node alpha hardfork config to
alphaTimefor the timestamp-gated reth change. - Builds the randomness Solidity test contracts inside the Docker e2e runner so new cases have fresh artifacts.
Dependencies (greth)
- chore(deps): bump gravity-reth to 3fd603db (persist.merge-blocks + pipe gas_limit + hardfork cleanup) by @nekomoto911 in #760
- Bumps greth
1aec7b75 → 3fd603db, picking up three landed greth PRs — see gravity-reth changes since v1.7.2 below. - Note: v1.7.2 was tagged on 2026-06-25 with the old
1aec7b75pin — greth#358 (merged 2026-06-24) is not in v1.7.2; this bump is the first time it lands in gravity-sdk.
- Bumps greth
gravity-reth changes since v1.7.2
The greth pin moved from 1aec7b75 to 3fd603db. Three commits:
#358 fix(pipe): close gravity-audit#621 + gravity-audit#712 (3fd603db)
Two consensus-critical fixes to pipe-execution gas_limit plumbing:
- audit-#712 (HIGH, consensus divergence). Block
gas_limitwas sourced from the per-node--gravity.pipe-block-gas-limitCLI flag, so validators with mismatched CLI values produced different block hashes from the sameOrderedBlock. Hardcoded to a single workspace constPIPE_BLOCK_GAS_LIMIT = 1_000_000_000; the CLI flag, config field, and all init shims are removed (mainnet pre-launch, no compat needed). - audit-#621 (HIGH, gas_used > gas_limit). System txns (metadata + DKG/JWK) ran before user-tx filtering, then had their gas appended to the block via
SystemTxnResult::insert_to_executed_ordered_block_result. The filter received the fullblock.gas_limitas budget, so a saturating user block plus non-trivial system overhead could pushheader.gas_used > header.gas_limitin release builds (validate_execution_outputis debug-only). Fix: passsum_system_gas(exact, computed from already-executed system results) intocreate_block_for_executorand applyblock.gas_limit.saturating_sub(sum_system_gas)to the filter budget;saturating_subcovers the byzantine path.block.header.gas_limititself is unchanged so RPC / indexer semantics stay stable.
#361 chore: remove gravity hardfork stubs
Drops dead hardfork scaffolding.
#362 feat(persistence): gravity.persist.merge-blocks (default off)
Coalesces consecutive blocks into gas/state-bounded groups (MERGE_GROUP_MAX_GAS = 1e9, MERGE_GROUP_MAX_STATE = 1e6 changed accounts) and commits each group with one fsync. Targets from-genesis PFN catch-up which is fsync-bound on the per-block path. Group is atomic (crash rolls back, recovery re-executes idempotently from stage checkpoints). Default-off path is byte-for-byte unchanged. Also removes the unused --gravity.validator-node-only flag.