Skip to content

Fix BLS12-381 precompile activation and harden dev-support scripts#3426

Merged
Pana merged 1 commit intoConflux-Chain:masterfrom
ChenxingLi:worktree-fix-bls12-activation
Apr 15, 2026
Merged

Fix BLS12-381 precompile activation and harden dev-support scripts#3426
Pana merged 1 commit intoConflux-Chain:masterfrom
ChenxingLi:worktree-fix-bls12-activation

Conversation

@ChenxingLi
Copy link
Copy Markdown
Contributor

@ChenxingLi ChenxingLi commented Apr 2, 2026

Background

Conflux's activation mechanism has gone through a gradual migration from block-number-based to epoch-height-based triggers.

In the early design, precompile and EVM feature activations all used DAG block numbers, mirroring the EVM number opcode exposed to contracts. Because smart contracts had no way to query epoch height, block number was the only on-chain signal available to them for detecting spec changes. Only consensus-layer features (which are invisible to contracts) used epoch heights.

Two developments shifted this design:

  1. eSpace became the primary execution environment. With eSpace, a single block corresponds to an epoch in core space, which contains multiple DAG blocks; activating by block number means eSpace can change behaviour mid-epoch, which is semantically wrong for an EVM-compatible space.
  2. Core space gained epoch-height introspection via the ConfluxContext internal contract, removing the original constraint that contracts could only observe block numbers.

As a result, newer features activate by epoch height. CIP-133 (Enhanced Block Hash Query) is the most illustrative case: it distinguishes core space (cip133b, block-number-triggered) from eSpace (cip133e, epoch-height-triggered). Going forward, all EVM-layer activations are expected to migrate to epoch height.

The Bug (EIP-2537)

eip2537 is declared in TransitionsEpochHeight — an epoch height value. However, before this fix, Builtin::activate_at was a plain u64, and is_active compared it against env.number (the DAG block number) regardless of what the stored value represented.

Because DAG block numbers grow approximately 2× faster than epoch heights, the BLS12-381 precompiles activated roughly 2× earlier than configured, meaning they would be available at an epoch that is far below the intended threshold.

Fix

Commit 1 — fix(executor): correct BLS12-381 precompile activation to use epoch height

ActivateAt enum (builtin/mod.rs)

Replace the bare u64 field with a typed enum:

pub enum ActivateAt {
    ByBlockNumber(u64),
    ByEpochHeight(u64),
}

is_active now takes both block_number and epoch_height and dispatches on the variant, so the correct counter is always used.

Extension traits (machine/mod.rs)

Two private traits, ActivateByNumbers and ActivateByHeights, are implemented on TransitionsBlockNumber and TransitionsEpochHeight respectively. Each exposes an activate_at(f) method that accepts a field-selector closure typed against the concrete struct:

// OK — eip2537 exists in TransitionsEpochHeight
params.transition_heights.activate_at(|t| t.eip2537)

// Compile error — eip2537 does not exist in TransitionsBlockNumber
params.transition_numbers.activate_at(|t| t.eip2537)

This makes the category of bug impossible to reintroduce silently.

Callsites (context.rs, stack/executable.rs)

Machine::builtin now receives both block_number and epoch_height, both sourced from env, so the correct value reaches each Builtin.

Commit 2 — fix: harden dev-support scripts and consensus_bench workspace isolation

Four small fixes uncovered while running test.sh end-to-end in a worktree:

Removed, the first 2 issues have been resolved by PR #3442 , the CXXFLAGS issue have been resolved by PR #3441, the others is to be resolved after merging #3442.

File Change
activate_new_venv.sh Guard uv venv with [ ! -d .venv ] so repeated runs do not recreate the virtualenv
dep_pip3.sh Skip pip install uv when uv is already on PATH, avoiding PEP 668 errors on system Python
test.sh Add CXXFLAGS=-Wno-error=array-bounds to suppress a C++ build failure on newer GCC; fix symlink bug: rm -f target silently fails when target/ is a real directory, causing ln -s build target to create a dangling link inside the directory — changed to rm -rf target
tools/consensus_bench/Cargo.toml Add [workspace] to make it a standalone workspace root, preventing Cargo from resolving upward to the parent repository's workspace when the worktree is nested inside it

Test Plan

Before merging the current branch into the production environment, restart tests must be conducted on both the mainnet and testnet! This is because the activation time of the relevant feature has actually been moved forward (earlier than originally planned). We want to verify that no calls were made to the relevant code paths during the period between the actual activation time and the originally expected activation time.


This change is Reviewable

Closes #3375

…eight

Introduce `ActivateAt` enum to distinguish block-number-based and
epoch-height-based builtin activation, fixing a type mismatch where
`transition_heights.eip2537` (an epoch height) was stored as `activate_at`
but compared against `env.number` (a DAG block number) in `is_active`.
Because DAG block numbers grow ~5x faster than epoch heights, BLS12-381
was activating roughly 5x earlier than configured.

Add private extension traits `ActivateByNumbers` / `ActivateByHeights` on
`TransitionsBlockNumber` / `TransitionsEpochHeight` in `machine/mod.rs`.
These accept a field-selector closure typed against the concrete struct,
making `transition_numbers.activate_at(|t| t.eip2537)` a compile error and
eliminating the class of mismatches at the source.
@ChenxingLi ChenxingLi force-pushed the worktree-fix-bls12-activation branch from 9868f35 to af404f0 Compare April 14, 2026 08:41
Copy link
Copy Markdown
Contributor

@peilun-conflux peilun-conflux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peilun-conflux reviewed 4 files and all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on ChenxingLi).

ChenxingLi added a commit to ChenxingLi/conflux-rust that referenced this pull request Apr 14, 2026
Remaining items from PR Conflux-Chain#3426 after PRs Conflux-Chain#3441 and Conflux-Chain#3442:

- test.sh: `rm -f target` → `rm -rf target` — rm -f silently fails on
  real directories, causing ln -s to create a link inside the directory
  instead of replacing it
- tools/consensus_bench/Cargo.toml: add [workspace] to prevent Cargo
  from resolving upward to the parent repo's workspace when the worktree
  is nested inside it
- tools/evm-spec-tester/Cargo.toml: same fix, same root cause

New: add fmt check to test.sh as a pre-phase before the build. Jenkins
Master lacks the nightly toolchain so fmt checking runs on Worker via
test.sh. Uses independent anchors (=== Fmt check ===) to avoid
renumbering existing phases.

Update SKILL.md monitoring guide: pipe-based launch to avoid tee
/dev/stderr log corruption, expanded phase regex for fmt anchors,
pre-flight fmt check, and fmt phase documentation.
@Pana Pana merged commit c8d419c into Conflux-Chain:master Apr 15, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BLS activate number should use block number otherwise height

3 participants