Skip to content

feat(l2): integrate Phylax Credible Layer into L2 sequencer#6488

Draft
avilagaston9 wants to merge 17 commits intofeat/l1/prestate-tracerfrom
feat/l2/circuit-breaker-integration
Draft

feat(l2): integrate Phylax Credible Layer into L2 sequencer#6488
avilagaston9 wants to merge 17 commits intofeat/l1/prestate-tracerfrom
feat/l2/circuit-breaker-integration

Conversation

@avilagaston9
Copy link
Copy Markdown
Contributor

@avilagaston9 avilagaston9 commented Apr 15, 2026

Depends on: #6496 (eth_subscribe/eth_unsubscribe WS support) — must be merged first.

Motivation

Integrate the Phylax Credible Layer into ethrex's L2 sequencer. This allows protocol teams to write Solidity-based security assertions that are validated against every transaction before block inclusion — violating transactions are silently dropped.

Description

When enabled via --credible-layer, the L2 block producer communicates with the Credible Layer Assertion Enforcer sidecar via gRPC during block building. For each candidate transaction, a Transaction event is sent to the sidecar, which evaluates it against registered assertions. If ASSERTION_FAILED, the transaction is dropped. On any error or timeout, transactions are included (permissive behavior — liveness over safety).

Implementation:

  • gRPC client (tonic/prost) implementing sidecar.proto (StreamEvents bidirectional stream, GetTransaction polling)
  • Block building hooks in fill_transactions: per-tx Credible Layer check for non-privileged txs, NewIteration/CommitHead lifecycle events
  • L2 WebSocket server with eth_subscribe("newHeads") — required by the sidecar for live chain state tracking (implemented in feat(l1): add eth_subscribe/eth_unsubscribe WebSocket subscription support #6496)
  • prestateTracer (diff mode) for debug_traceBlockByNumber — required by the sidecar to build its local state DB
  • eth_getLogs fix: accept requests without topics parameter (Ethereum spec compliance, needed by the sidecar's assertion indexer)
  • Test contracts (OwnableTarget.sol, TestOwnershipAssertion.sol), mock sidecar binary, and e2e validation script

How to Test

Full end-to-end guide in docs/l2/credible_layer.md — 10 verified steps from L1 startup to assertion rejection. Summary:

  1. Start L1, deploy L2 contracts, start L2 with --credible-layer
  2. Deploy State Oracle on L2 using Phylax's credible-layer-contracts Forge scripts
  3. Deploy OwnableTarget, compile OwnableAssertion from credible-layer-starter, upload to assertion DA, register on State Oracle
  4. Start sidecar-indexer (Docker) + real Phylax sidecar (Docker)
  5. Send transferOwnershipdropped (assertion violation detected by real sidecar)
  6. Send doSomething()included (no assertion triggered)

Tested end-to-end with the real Phylax sidecar Docker image (ghcr.io/phylaxsystems/credible-sdk/sidecar:main), assertion-da, sidecar-indexer, and credible-layer-contracts deployment scripts.

Checklist

  • Code compiles (cargo check -p ethrex --features l2)
  • Unit tests pass
  • End-to-end tested with real Phylax sidecar
  • Documentation: docs/l2/credible_layer.md with verified step-by-step guide
  • Zero overhead when disabled (no gRPC calls when --credible-layer is not set)
  • CI passing (pending)

@avilagaston9 avilagaston9 self-assigned this Apr 15, 2026
@avilagaston9 avilagaston9 changed the title Integrate Phylax Credible Layer (Circuit Breaker) into L2 sequencer feat(l2): integrate Phylax Credible Layer (Circuit Breaker) into L2 sequencer Apr 15, 2026
@avilagaston9 avilagaston9 changed the title feat(l2): integrate Phylax Credible Layer (Circuit Breaker) into L2 sequencer feat(l2): integrate Phylax Credible Layer into L2 sequencer Apr 15, 2026
Add optional transaction validation against the Credible Layer Assertion
Enforcer sidecar during L2 block building. When enabled via --circuit-breaker-url,
each candidate transaction is sent to the sidecar via gRPC. If the sidecar
returns ASSERTION_FAILED, the transaction is dropped from the block. On any
error or timeout, the transaction is included (permissive / liveness over safety).

Changes:
- gRPC client (tonic/prost) implementing sidecar.proto StreamEvents + GetTransaction
  and aeges.proto VerifyTransaction for optional mempool pre-filtering
- Block producer sends NewIteration, Transaction, and CommitHead events via
  a persistent bidirectional gRPC stream with automatic reconnection
- L2 WebSocket server with eth_subscribe("newHeads") support, required by
  the sidecar for live chain state tracking
- prestateTracer (diff mode) for debug_traceBlockByNumber, required by the
  sidecar to build its local state database
- Fix eth_getLogs to accept requests without topics parameter (spec compliance)
- CLI flags: --circuit-breaker-url, --circuit-breaker-aeges-url,
  --circuit-breaker-state-oracle, --l2.ws-enabled/addr/port
- Test contracts (OwnableTarget.sol, TestOwnershipAssertion.sol),
  mock sidecar binary, and e2e validation script
- Documentation with verified 10-step end-to-end guide covering L1 setup,
  L2 with circuit breaker, State Oracle deployment via Phylax Forge scripts,
  assertion registration via DA + State Oracle, real sidecar with indexer,
  and transaction rejection/inclusion verification

Tested end-to-end with the real Phylax sidecar Docker image, assertion-da,
sidecar-indexer, and credible-layer-contracts Forge deployment scripts.
…naming

Circuit Breaker was an informal name. Phylax's official product name is
Credible Layer — used consistently across all their documentation, code,
and repos. Rename all references: module directories, struct names, CLI
flags, env vars, docs, and Makefile targets.
Build with COMPILE_CONTRACTS=true once in prerequisites, then use the
binary directly in Step 2 instead of cargo run which triggers a rebuild.
block production. Adds a stream_connected flag that the background task
sets/clears. When false, evaluate_transaction returns true immediately
instead of polling GetTransaction (which would timeout and block the
block producer for ~2s per tx).
Docker logs contain ANSI escape sequences that break plain grep matching.
Add sed pipe to strip them in all docker logs grep commands.
… doc improvements

Add a --credible-layer boolean gate flag to CredibleLayerOptions (modeled after --aligned),
so operators explicitly opt in before providing any --credible-layer-* sub-flags. The three
sub-flags (--credible-layer-url, --credible-layer-aeges-url, --credible-layer-state-oracle)
now carry requires = "credible_layer". The TryFrom mapping returns CredibleLayerConfig::default()
when the gate flag is absent.

Promote three log messages in client.rs from debug to info/warn: forwarding events is useful
for operators to trace the event flow (info), while StreamEvents connect failures and channel
closure are anomalies that deserve visibility (warn). The GetTransaction poll-attempt message
stays at debug since it fires on every poll attempt.

Update credible_layer.md: clarify the privileged-tx bypass is specific to this first version
of the integration, expand Key Files descriptions to distinguish the sidecar client from the
Aeges client by listing their RPCs, reflect the new --credible-layer gate flag in the
Configuration table and the Step 3 startup command, simplify RUST_LOG to plain "info" since
the important Credible Layer messages are now at INFO/WARN level, replace cast commands with
rex equivalents (block-number, send -k, call, address -k), and remove cast from the
Prerequisites list (only forge is now required).
rex deploy can compile and deploy Solidity directly, no need for
manual solc compilation + cast send --create.
…mentation exists)

Deletes the Aeges gRPC client module (aeges.rs), its proto definition (aeges.proto),
the --credible-layer-aeges-url CLI flag, the aeges_url field from CredibleLayerConfig,
the MempoolFilter type and mempool_filter field from RpcApiContext, the build_aeges_filter
function from initializers, and all related wiring in start_api. Updates docs/CLI.md,
docs/l2/credible_layer.md, and the Makefile init-l2-credible-layer target accordingly.
…m L2 to L1 RPC crate.

The subscription functionality (newHeads) is standard Ethereum behavior that belongs in the
base execution client, not L2-specific code. The L1 RpcApiContext now carries a
new_heads_sender field, and the subscription functions (handle_eth_subscribe,
handle_eth_unsubscribe, generate_subscription_id, drain_subscriptions,
build_subscription_notification) and the NEW_HEADS_CHANNEL_CAPACITY constant are defined
in the L1 crate and exported from its lib.rs.

The L1 handle_websocket is upgraded from a simple request-response loop to a select!-based
loop that multiplexes incoming WS messages with subscription notification draining.

The L2 WS handler is simplified to delegate eth_subscribe and eth_unsubscribe to L1's
implementations (via context.l1_ctx), eliminating the duplicate code. The L2 lib.rs
re-exports NEW_HEADS_CHANNEL_CAPACITY from ethrex_rpc for backward compatibility with
existing callers (cmd/ethrex/l2/initializers.rs).

The L2 tests that covered the subscription utilities are updated to reference the L1
implementations directly.
@avilagaston9 avilagaston9 force-pushed the feat/l2/circuit-breaker-integration branch from e311925 to 9d8569b Compare April 16, 2026 15:29
@github-actions github-actions bot added the L2 Rollup client label Apr 16, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 16, 2026

Lines of code report

Total lines added: 1111
Total lines removed: 1
Total lines changed: 1112

Detailed view
+--------------------------------------------------------------+-------+------+
| File                                                         | Lines | Diff |
+--------------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex/l2/options.rs                              | 1144  | +40  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/blockchain/tracing.rs                          | 187   | +57  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/common/tracing.rs                              | 266   | +219 |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/build.rs                                    | 14    | +3   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/networking/rpc/rpc.rs                       | 255   | -1   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/block_producer.rs                 | 422   | +99  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/block_producer/payload_builder.rs | 342   | +108 |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/configs.rs                        | 114   | +6   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/credible_layer/client.rs          | 389   | +389 |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/credible_layer/errors.rs          | 14    | +14  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/credible_layer/mod.rs             | 7     | +7   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/mod.rs                            | 278   | +1   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/tracing.rs                      | 228   | +52  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/tracing.rs                    | 159   | +94  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/tracing.rs                                  | 65    | +22  |
+--------------------------------------------------------------+-------+------+

@avilagaston9 avilagaston9 changed the base branch from main to feat/l1/ws-subscriptions April 16, 2026 15:46
Integrates the SubscriptionManager actor refactoring (replacing broadcast channels)
with the Credible Layer integration. Updates WS CLI flags in the credible layer guide
from the removed --l2.ws-enabled/--l2.ws-port to --ws.enabled/--ws.port, fixes
rex address and rex deploy command syntax, and removes unused TxExecutionId import.
…_build.

The mock sidecar was a standalone dev tool for testing the gRPC protocol
without the real Phylax sidecar, but it was never referenced by any
Makefile target, script, test, or documentation.
…ectly

preserved during the merge and is unrelated to the Credible Layer integration.
@avilagaston9 avilagaston9 changed the base branch from feat/l1/ws-subscriptions to feat/l1/prestate-tracer April 17, 2026 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L2 Rollup client

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant