mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
evm/core: release-gate the cross-repo DexSettleActivationTime DRY guard behind a build tag
The guard TestDexSettleActivationTime_LayerMirrorsMatch references dex.DexSettleActivationTime, which is defined in luxfi/precompile and post-dates evm/go.mod's pinned precompile tag (v0.5.54). Under GOWORK=off (CI), evm/core failed to build (undefined: dex.DexSettleActivationTime); it only compiled via an untracked local go.work. The guard was therefore both inert in CI and a latent CI break. Move the single cross-repo guard into precompile_alwayson_dexsettle_guard_test.go behind //go:build dexsettle_guard. Default CI excludes it, so evm/core builds and tests against the pinned precompile tag with no go.work. The release step bumps evm/go.mod to a precompile tag that exports the symbol and runs `go test -tags dexsettle_guard ./core/`, enforcing the DRY invariant atomically with the bump. precompile cannot host the guard (it does not import luxfi/evm; the graph is strictly evm->precompile, so referencing extras.DexSettleActivationTime from precompile would create a cycle). All other 0x9999 activation pins in precompile_alwayson_test.go use only evm-local symbols and run on every CI build.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
//go:build dexsettle_guard
|
||||
|
||||
// This file holds the ONE cross-repo DRY guard that pins the 0x9999 activation
|
||||
// timestamp across the two layers that cannot share a Go symbol:
|
||||
//
|
||||
// - the CANONICAL definition, extras.DexSettleActivationTime (this evm layer),
|
||||
// - the layer-local MIRROR, dex.DexSettleActivationTime (luxfi/precompile).
|
||||
//
|
||||
// It is RELEASE-COUPLED on purpose. dex.DexSettleActivationTime lives in
|
||||
// luxfi/precompile; evm/go.mod must be bumped to a precompile version that
|
||||
// EXPORTS that symbol before this guard can compile. Because the precompile tag
|
||||
// is published by CI/CD (never from a dev checkout), keeping this test always-on
|
||||
// would make evm/core fail to build (`undefined: dex.DexSettleActivationTime`)
|
||||
// against any precompile tag predating the symbol — a silent CI break that only
|
||||
// an untracked local go.work could paper over.
|
||||
//
|
||||
// The `dexsettle_guard` build tag decouples WHAT the guard asserts from WHEN it
|
||||
// is compiled. Default CI (`go test ./core/`) excludes this file, so evm/core
|
||||
// builds and tests against the pinned precompile tag with no go.work. The release
|
||||
// step that bumps evm/go.mod to precompile >= the symbol-exporting tag runs:
|
||||
//
|
||||
// go test -tags dexsettle_guard ./core/
|
||||
//
|
||||
// at which point dex.DexSettleActivationTime exists and the DRY invariant is
|
||||
// enforced atomically with the bump. See the release checklist in
|
||||
// precompile_alwayson_test.go's package doc and LLM.md.
|
||||
//
|
||||
// Everything else about 0x9999 activation (dispatch gate, marker install, the
|
||||
// override race, replay safety) is pinned UNCONDITIONALLY in
|
||||
// precompile_alwayson_test.go using only evm-local symbols — those run on every
|
||||
// CI build. Only this cross-repo symbol equality is tag-gated.
|
||||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/evm/params/extras"
|
||||
// dex provides the layer-local mirror DexSettleActivationTime asserted equal
|
||||
// to the canonical extras value here. This is the ONLY reference in evm to a
|
||||
// precompile symbol that may post-date evm/go.mod's pinned precompile tag,
|
||||
// which is exactly why this file is behind the dexsettle_guard build tag.
|
||||
"github.com/luxfi/precompile/dex"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestDexSettleActivationTime_LayerMirrorsMatch is the DRY-safety guard for the
|
||||
// 0x9999 activation timestamp. It imports BOTH layers' constants and fails CI the
|
||||
// instant either moves without the other. If the two drift, a settlement could
|
||||
// dispatch (gated by extras) at a timestamp where the precompile withholds its log
|
||||
// (gated by the stale mirror) — or vice versa — opening a settlement-without-log /
|
||||
// log-without-settlement window and a consensus split on replay.
|
||||
func TestDexSettleActivationTime_LayerMirrorsMatch(t *testing.T) {
|
||||
require.Equal(t, extras.DexSettleActivationTime, dex.DexSettleActivationTime,
|
||||
"dex.DexSettleActivationTime (precompile layer-local mirror) must equal the canonical extras.DexSettleActivationTime; "+
|
||||
"the DEX log gate and the EVM dispatch gate MUST fire on the same dated fork")
|
||||
}
|
||||
@@ -16,9 +16,6 @@ import (
|
||||
// registry side-effect: bridges the external DEX settlement module (0x9999)
|
||||
// into the EVM's internal registry so it is visible as AlwaysOn here.
|
||||
_ "github.com/luxfi/evm/precompile/registry"
|
||||
// dex provides the layer-local mirror DexSettleActivationTime asserted equal to
|
||||
// the canonical extras value by TestDexSettleActivationTime_LayerMirrorsMatch.
|
||||
"github.com/luxfi/precompile/dex"
|
||||
"github.com/luxfi/geth/common"
|
||||
"github.com/luxfi/geth/core/rawdb"
|
||||
"github.com/luxfi/geth/core/tracing"
|
||||
@@ -53,25 +50,16 @@ const (
|
||||
tsPostActivation uint64 = extras.DexSettleActivationTime + 86_400
|
||||
)
|
||||
|
||||
// TestDexSettleActivationTime_LayerMirrorsMatch is the DRY-safety guard for the
|
||||
// 0x9999 activation timestamp, which exists in TWO layers that cannot share a symbol:
|
||||
//
|
||||
// - the CANONICAL definition, extras.DexSettleActivationTime (this evm layer), is what
|
||||
// the dispatch gate (GetExtrasRules) and the marker-installing state transition use;
|
||||
// - a layer-local MIRROR, dex.DexSettleActivationTime (luxfi/precompile), which the DEX
|
||||
// precompile uses to gate its NEW consensus-visible logs (DEXFill, the native V4
|
||||
// Initialize) as defense in depth — the precompile sits BELOW evm in the import graph
|
||||
// (evm imports precompile, never the reverse) so it cannot import the extras constant.
|
||||
//
|
||||
// If these two drift, a settlement could dispatch (gated by extras) at a timestamp where
|
||||
// the precompile withholds its log (gated by the stale mirror) — or vice versa — opening a
|
||||
// settlement-without-log / log-without-settlement window and a consensus split on replay.
|
||||
// This test imports BOTH and fails CI the instant either constant moves without the other.
|
||||
func TestDexSettleActivationTime_LayerMirrorsMatch(t *testing.T) {
|
||||
require.Equal(t, extras.DexSettleActivationTime, dex.DexSettleActivationTime,
|
||||
"dex.DexSettleActivationTime (precompile layer-local mirror) must equal the canonical extras.DexSettleActivationTime; "+
|
||||
"the DEX log gate and the EVM dispatch gate MUST fire on the same dated fork")
|
||||
}
|
||||
// The cross-layer DRY guard that pins extras.DexSettleActivationTime ==
|
||||
// dex.DexSettleActivationTime (luxfi/precompile's layer-local mirror) lives in
|
||||
// precompile_alwayson_dexsettle_guard_test.go behind the `dexsettle_guard` build
|
||||
// tag. It is RELEASE-COUPLED: dex.DexSettleActivationTime sits BELOW evm in the
|
||||
// import graph (evm imports precompile, never the reverse), so evm/go.mod must be
|
||||
// bumped to a precompile tag that EXPORTS the symbol before that guard can compile.
|
||||
// Default CI excludes it (so evm/core builds against the pinned precompile tag with
|
||||
// no go.work); the release step runs `go test -tags dexsettle_guard ./core/` after
|
||||
// the go.mod bump so the invariant is enforced atomically with it. Everything in
|
||||
// THIS file uses only evm-local symbols and runs on every CI build.
|
||||
|
||||
// TestAlwaysOn_9999_Registered asserts the DEX settlement precompile bridges into the
|
||||
// EVM registry as AlwaysOn and is enumerated by AlwaysOnModules().
|
||||
|
||||
Reference in New Issue
Block a user