Conversation
…5763) ## Motivation With the monotonic increase of `nextBlockHeight` in `Microchain.sol` it's more complicated to keep the messages relayed in a correct order. ## Proposal BFT-finalized certificates already guarantee block canonicality — a quorum of validators cannot sign two conflicting blocks at the same height. The sequential height check added no security value while forcing the relayer to submit every block (including irrelevant ones) in strict order, wasting gas and adding fragility. The verifiedBlocks mapping continues to prevent duplicate processing. ## Test Plan CI ## Release Plan None ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
## Motivation Bridge e2e tests are failing again. ## Proposal Update docker compose to not pass the nextExpectedHeight which was removed in #5763 ## Test Plan CI ## Release Plan None ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
Post `testnet_conway` merge job is broken. Comiple the `evm-bridge` contract. CI None for now - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
Right now exporters are crashing on the indexer's ack stream. Until we fix the root cause, add `/health` endpoint which returns 500 whenever we get a non-recoverable error on any of the streams. CI and manual - Test on conway, then backport. - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
The bridge verifies EVM block finality before processing deposits. The
source chain is Base (OP Stack L2, chain ID 8453), which changes the
threat model:
- L2 RPC providers more commonly misconfigure endpoints (Base Mainnet vs
Sepolia vs other OP Stack chains)
- The `"finalized"` tag has different semantics on OP Stack (tracks L1
finality of the L2 batch)
- 2-second block times mean cache grows 6x faster than L1
- Add `rpc_endpoint` field to `BridgeParameters` and
`verified_block_hashes` to contract state
- `ProcessDeposit` verifies block hash finality inline when
`rpc_endpoint` is configured, querying the source EVM chain
(`eth_getBlockByHash` + `eth_getBlockByNumber("finalized")`)
- Add `VerifyBlockHash` operation for pre-verification; caches the hash
only when submitted by an authenticated signer (chain owner) to prevent
state bloat
- `ProcessDeposit` also caches verified block hashes after replay
protection, so subsequent deposits from the same block skip the RPC
check
- Log a warning when `rpc_endpoint` is empty and finality verification
is skipped
- Add `get_chain_id()` to the `EthereumQueries` trait in
`linera-ethereum`
- Validate the RPC endpoint's chain ID matches `source_chain_id` during
`instantiate()`, catching misconfigured endpoints at deploy time
- Add `ProofError` enum (transient vs permanent) to deposit proof
generation
- Transient: receipt not found, block not found, RPC transport errors →
retry with backoff
- Permanent: header hash mismatch, receipts root mismatch, no
DepositInitiated event → return 400 immediately
- `thiserror` dependency gated behind `offchain` feature so it doesn't
leak into examples
- Retry deposit proof generation up to 5 times with linear backoff
(public testnet RPCs may not have indexed the receipt immediately)
- Permanent errors fail immediately with `400 BAD_REQUEST` instead of
wasting 20s retrying
- Add structured `tracing` logs throughout the deposit handler and main
loop
- Accurate for any EVM-compatible JSON-RPC endpoint, not just Ethereum
L1
- Add fallible `try_create_application` to `ActiveChain` in `linera-sdk`
test framework
- Auto-detect `linera` / `linera-bridge` binaries from `target/debug`,
`target/release`, or `$PATH`
- Wait for EVM transaction inclusion after each `forge create` to avoid
nonce races on public testnets
- Add `sync` + `process-inbox` steps before Linera app deployments
- Pass `EVM_RPC_URL` into evm-bridge application parameters
- Run bridge e2e workflow on `pull_request` events
- Update README with Conway testnet faucet URL and improved `SHARED_DIR`
instructions
- `cargo test -p linera-ethereum --features ethereum` — all Anvil tests
pass including new `test_get_chain_id`
- `cargo test --manifest-path examples/evm-bridge/Cargo.toml` — 9
unit/integration tests pass including
`test_instantiation_fails_with_unreachable_endpoint`
- `cargo test --manifest-path examples/evm-bridge/Cargo.toml --
--ignored` — 2 Anvil tests pass (`test_verify_block_hash_anvil`,
`test_verify_block_hash_not_found`)
- `cargo test -p linera-bridge` — proof/relay tests pass
- `cargo clippy -p linera-bridge --lib --features chain
--no-default-features` — confirms no `thiserror` leakage into examples
- Nothing to do / These changes follow the usual release cycle.
Closes #5629
- [reviewer
checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
The bridge relay (`linera-bridge serve`) used ephemeral in-memory storage and generated fresh keypairs on every startup. Every restart required re-claiming a chain from the faucet, invalidating all deployed EVM contracts that reference the old chain ID. On testnets this forced full redeployment of everything. Additionally, the relay's CLI was inconsistent with the `linera` binary — it used custom `--data-dir` and file-polling flags instead of the standard `--wallet`, `--keystore`, `--storage` pattern. `GenesisConfig` (from `linera-client`) and `PersistentWallet` (from `linera-service`) are moved to `linera-core` to break the cyclic dependency that prevented `linera-bridge` from using these types. Both are re-exported from their original locations for backward compatibility. A new `fs` feature on `linera-core` gates the `linera-persistent` dependency. The relay now accepts the same `--wallet`, `--keystore`, `--storage` flags and `LINERA_WALLET`/`LINERA_KEYSTORE`/`LINERA_STORAGE` env vars as the `linera` binary, defaulting to `~/.config/linera/`. It uses `PersistentWallet` for chain metadata and RocksDB for block storage. `--linera-bridge-chain-id` selects a pre-existing chain (syncs from validators, verifies the keystore contains an owner key). Without it, a new chain is claimed from the faucet. File polling is removed — `--evm-bridge-address`, `--linera-bridge-address`, and `--linera-fungible-address` are required directly. A new `bridge-chain-init` compose service claims the bridge chain before the relay starts. The `--http-request-allow-list` flag is added to `linera net up` (configurable via `HTTP_REQUEST_ALLOW_LIST` env var) for EVM finality verification. `setup.sh` accepts `--linera-wallet`, `--linera-keystore`, `--linera-storage` to use an existing wallet (or respects env vars). It no longer claims its own chain and prints all deployed addresses with a ready-to-copy relay command at the end. 1. `linera wallet init --faucet <URL>` 2. `linera wallet request-chain --faucet <URL>` 3. `setup.sh --linera-bridge-chain-id <ID> --relay-owner <OWNER> ...` 4. `linera-bridge serve --linera-bridge-chain-id <ID> ...` - `cargo test -p linera-bridge` — all 72 unit tests pass - `cargo clippy -p linera-bridge --features relay` — clean - All 3 Docker e2e tests pass (`committee_rotation`, `evm_to_linera_bridge`, `fungible_bridge`) - Manual testnet deployment verified (Base Sepolia + Conway testnet) - Nothing to do / These changes follow the usual release cycle. - Resolves #5704 - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
## Motivation Bridge e2e task is currently failing - fix it. ## Proposal Don't add `--http-request-allow-list` in docker compose of the bridge test if it's not set. Should make the CI green and unblock docker image publishing. ## Test Plan CI ## Release Plan None. ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
…ing requests. (#5793) The linera-bridge relay had no visibility into the state of bridging requests. If a deposit was made on EVM but the relay crashed mid-processing, tokens would be locked on EVM with no minted counterpart on Linera — and nobody would know. Similarly, if a Linera→EVM burn was detected but the certificate failed to forward to EVM, the burn would be silently lost. Add active monitoring and automatic retry to the bridge relay, so it self-heals without operator intervention. Add `/metrics` endpoint where we serve Prometheus metrics. Replace scattered `provider`/`chain_client` clones with single `EvmClient` and `LineraClient` instances shared via `Arc`. All chain write operations (`ProcessDeposit`, `Burn`, `ProcessInbox`) go through an mpsc channel to the main loop, eliminating quorum conflicts from concurrent block proposals. - `EvmClient<P>`: wraps alloy Provider with typed API (`get_deposit_logs`, `get_transfer_logs`, `forward_cert`) - `LineraClient<E>`: read operations use ChainClient directly (safe on clones), write operations serialized through channel - **EVM scan loop**: polls `DepositInitiated` events from the FungibleBridge contract, checks Linera for completion via `isDepositProcessed` GraphQL query - **Linera scan loop**: walks block history for Credit-to-Address20 messages, checks EVM for completion via ERC-20 `Transfer` events - Scan loops send newly discovered pending items to retry loops via channels - **Deposit retry**: generates MPT proof from `tx_hash` and submits `ProcessDeposit` to Linera (on-chain `processed_deposits` prevents double-minting) - **Burn retry**: submits Burn via channel to main loop, forwards cert to EVM directly (EVM `verifiedBlocks` prevents duplicates) - Exponential backoff (5s → 80s cap) with configurable max retries - Guards against duplicate processing: checks `forwarded` status and sets `last_retry_at` before starting work - **Fixed duplicate burn/deposit processing**: scan loop re-enqueue could race with in-progress retry, causing double Burn submissions. Now sets `last_retry_at` at processing start and skips already-completed items. - **Removed unnecessary cert forwarding**: inbox certs and deposit certs were forwarded to EVM but FungibleBridge ignored them (only burn certs trigger `_onBlock`) - **Fixed notification listener**: `extend_chain_mode()` was not called for pre-existing chains, preventing the relay from receiving `NewIncomingBundle` notifications - **Removed `/deposit` HTTP endpoint**: no longer needed since the scanner auto-detects deposits - **Frontend stale balance**: added 5s polling interval to catch relay-driven balance changes Replaced the monitor HTTP endpoints with a `/metrics` endpoint exposing: - `linera_bridge_deposits_detected`, `_completed`, `_pending`, `_failed` - `linera_bridge_burns_detected`, `_completed`, `_pending`, `_failed` - `linera_bridge_last_scanned_evm_block`, `_last_scanned_linera_height` - Split `monitor.rs` into `monitor/mod.rs`, `monitor/evm.rs`, `monitor/linera.rs` - Split `relay.rs` into `relay/mod.rs`, `relay/evm.rs`, `relay/linera.rs`, `relay/metrics.rs` - Introduced `Tracked<T>` generic wrapper to deduplicate `TrackedDeposit` / `TrackedBurn` - Added `fungible` and `wrapped-fungible` as dependencies to use real types instead of inline BCS parsing - Anvil: `--slots-in-an-epoch 1 --block-time 1` for EVM finality - Validator: `anvil` added to HTTP request allow list - Relay waits for `setup-complete` marker before starting - setup.sh: retry `publish-and-create` up to 3 times, pass `EVM_RPC_URL` to evm-bridge - `--monitor-scan-interval <SECONDS>` (default: 30) - `--monitor-start-block <NUMBER>` (default: 0) - `--max-retries <N>` (default: 10) - [x] 10 unit tests for `MonitorState`, backoff logic, deposit key hashing - [x] E2E test (`test_evm_to_linera_bridge`): verifies `isDepositProcessed` query before and after deposit - [x] E2E test (`test_auto_deposit_scan`): bidirectional — deposits auto-scanned on EVM and processed on Linera, burns auto-detected and forwarded to EVM with ERC-20 balance verification - [x] All existing E2E tests pass (`committee_rotation`, `evm_to_linera_bridge`, `fungible_bridge`) - [x] Docker image rebuilt and tested
## Motivation The bridge relayer needs to be deployable on infrastructure via Docker. The existing `Dockerfile.bridge` builds the binary but has no entrypoint, env var support, or exposed ports. Additionally, `--faucet-url` is unconditionally required even when running with a pre-existing wallet, which prevents standalone deployment without a faucet. ## Proposal - Add `bridge-entrypoint.sh` that maps environment variables to CLI args for the `serve` subcommand, with pass-through for other subcommands (`init-light-client`, `generate-deposit-proof`, `sh -c` wrappers). - Update `Dockerfile.bridge` runtime stage: ENTRYPOINT, CMD, EXPOSE 3001, ENV defaults for optional args, documented required/optional vars. - Make `--faucet-url` optional in the Rust code. It is now only required when the wallet doesn't exist (needs genesis config) or `--linera-bridge-chain-id` is not provided (needs to claim a chain). Admin chain sync uses `synchronize_from_validators()` instead of fetching the committee from the faucet. - Add Makefile targets: `build-relayer`, `relayer-up` (validates required env vars, prints config, runs container), `relayer-down`, `relayer-logs`. - Update `docker-compose.bridge-test.yml` relay service to use the new entrypoint. - Fix CI: add missing `cargo build -p linera-bridge --features relay` step for the `auto_deposit_scan` test which spawns a local relay binary. ## Test Plan - `cargo check -p linera-bridge --features relay` compiles clean - Docker image builds via `make -C linera-bridge build-relayer` - All bridge e2e tests pass locally: - `test_evm_to_linera_bridge` — EVM→Linera deposit with proof - `test_fungible_bridge` — Linera→EVM burn with ERC-20 balance verification - `test_auto_deposit_scan` — bidirectional: auto-scanned deposit + auto-forwarded burn ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
## Motivation The bridge relayer currently stores all deposit/burn request state in-memory via `MonitorState`. On restart, all request history is lost. We need persistent storage so that: 1. Request history survives restarts for auditing and debugging. 2. Requests can be queried by source, recipient, amount, timestamp, and status. 3. Raw BCS-serialized operation bytes can be `SELECT`ed and uploaded to the chains **without the relayer running**. ## Proposal Add a SQLite write-through layer alongside the existing in-memory `MonitorState`. Every mutation (track, complete, fail) now persists to SQLite in addition to updating the `HashMap`. **New file: `linera-bridge/src/monitor/db.rs`** - `BridgeDb` struct wrapping a `SqlitePool` - Two tables: `deposits` and `burns` with columns for source, recipient, amount, status, timestamps, and raw operation bytes (BCS-serialized `BridgeOperation::ProcessDeposit` for deposits, `ConfirmedBlockCertificate` for burns) - All writes are idempotent (`INSERT OR IGNORE` / `UPDATE`) **Changes to `MonitorState`:** - Holds an `Option<BridgeDb>` (None in tests without a DB) - `track_deposit`, `complete_deposit`, `track_burn`, `complete_burn`, `mark_*_failed` are now `async` and write through to SQLite internally **Raw bytes storage:** - Deposit proofs: BCS-serialized after proof generation in `monitor/evm.rs` - Burn certs: BCS-serialized after `linera_client.burn()` in `monitor/linera.rs` (panics on serialization failure since the cert must be serializable to forward to EVM) **CLI:** - New `--sqlite-path` option to override the default location (`bridge_relay.sqlite3` next to the RocksDB storage directory) - SQLite open failure is fatal (exits the binary) ## Test Plan - 9 unit tests parameterized via `test_case` across both in-memory and file-backed SQLite backends: insert, complete, fail, idempotency, raw bytes storage for both deposits and burns - 1 dedicated file persistence test verifying data survives close and reopen - All 92 existing `linera-bridge` tests continue to pass (`cargo test -p linera-bridge --features relay`) ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
## Motivation Bridge e2e tests are failing. Turns out the problem is non-deterministic choice of the owner from the wallet of bridge chain owner. Another issue was that logs were incorrectly sent to stdout which – if not consumed – would fill up the buffer (64k) and then block other processes from writing to it. Which, in our case, caused some problems down the line where things were read from the log output. ## Proposal For the logging issue, two fixes: 1. Initialize the tracing subscriber properly (using a method from `linera_base`) 2. For docker-compose based tests (via `test-containers` crate) we pipe do /dev/null. For the non-deteministic owner we add a new argument to the linera relayer `--linera-bridge-chain-owner` and specify exactly who's the owner. ## Test Plan CI ## Release Plan None for now. ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
- Add rocksdb feature to linera-storage - Adapt relay to main's API signatures (no StorageCacheSizes, 3-arg maybe_create_and_connect) - Use tracing_subscriber stderr writer instead of linera_base::tracing::init - Adapt linera-client config.rs to main's GenesisConfig structure - Add Bytecode::load_from_file_sync for non-async contexts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.