Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fd02b69
Drop Microchain.verifiedBlocks so subclasses own dedup
deuszx May 13, 2026
764bf5e
Add FungibleBridge.processBurns for per-tx chunked settlement
deuszx May 13, 2026
fd936d6
Add EvmClient gas-estimate + processBurns helpers
deuszx May 13, 2026
f7ce026
Add split_to_fit + estimate_fits pure helpers
deuszx May 13, 2026
2261d09
Add tx_index + event_pos_in_tx to PendingBurn schema and scanner
deuszx May 13, 2026
41946d0
Rewire process_pending_burns to use addBlock-then-chunked-processBurns
deuszx May 13, 2026
8b47891
Add e2e test exercising chunked processBurns fallback
deuszx May 13, 2026
0914f4c
Drop unreachable already-verified branch in process_pending_burns
deuszx May 13, 2026
14ed288
Apply checks-effects-interactions to burn dedup in FungibleBridge
deuszx May 13, 2026
5c9b710
Extract _burnKey + _isMatchingBurn + _releaseBurn helpers
deuszx May 13, 2026
dbd111f
Print error when wrapped fungible app publish fails
deuszx May 13, 2026
12127b7
Remove references to old code behavior
deuszx May 13, 2026
44abab5
forge fmt
deuszx May 13, 2026
044b7be
cargo fmt linera-bridge/tests/e2e
deuszx May 14, 2026
8dc74b5
processBurns: reject empty positions array
deuszx May 16, 2026
4fb7a64
processBurns: skip duplicates instead of reverting
deuszx May 16, 2026
ac3f648
is_gas_exceeded_error: drop "out of gas" generic fallback
deuszx May 16, 2026
a49bed6
pending_burns_by_height_and_tx: unify event_indices snapshot
deuszx May 16, 2026
960f679
MonitorState: add event_index_for_pos + filter failed in snapshot
deuszx May 16, 2026
fe5f602
process_pending_burns: per-burn retry accounting; isolate oversized
deuszx May 16, 2026
467e6ea
PendingBurnsAtHeight: tuple to struct; return BTreeSet ordered by height
deuszx May 16, 2026
07547c5
Extract submit_addblock/submit_chunked/split_to_fit helpers
deuszx May 16, 2026
9e88993
Clarify comments and renames
deuszx May 18, 2026
61ce1be
Add cert_hash to PendingBurnsAtHeight
deuszx May 18, 2026
4c5f706
Regenerate linera-bridge/evm-contracts Cargo.lock
deuszx May 18, 2026
8ac2aef
Align tracing logging pattern
deuszx May 18, 2026
9a70db9
Move is_gas_exceeded to where it's used
deuszx May 18, 2026
16f8fd0
Assert that we created multiple blocks to relay Linera Burns
deuszx May 18, 2026
df6e8a7
Mark deposits/burns as failed when they exhaust the retry limit
deuszx May 19, 2026
cef3519
Bump retry counter for blocks which fail the gas estimation as well
deuszx May 25, 2026
de88969
Address Andreas' comments
deuszx May 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/bridge-demo/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ for attempt in 1 2 3; do
--json-parameters "$WRAPPED_PARAMS" \
--json-argument '{"accounts":{}}' 2>&1) && break
echo " Attempt $attempt failed, retrying..." >&2
echo "$WRAPPED_APP_OUTPUT" >&2
sleep 2
done
[[ -z "$WRAPPED_APP_OUTPUT" ]] && { echo "ERROR: publish-and-create wrapped-fungible failed after retries" >&2; exit 1; }
Expand Down
3 changes: 3 additions & 0 deletions linera-bridge/contracts/evm-bridge/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions linera-bridge/src/evm/microchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,16 @@ mod tests {
}

#[test]
fn test_microchain_rejects_duplicate_block() {
fn test_microchain_accepts_duplicate_block() {
let mut microchain = TestMicrochain::new();

microchain.add_block(BlockHeight(1));

assert!(
microchain
.try_add_block(microchain.chain_id, BlockHeight(1))
.is_err(),
"should reject duplicate block"
.is_ok(),
"Microchain must accept duplicate addBlock calls; subclass owns dedup"
);
}

Expand Down
47 changes: 34 additions & 13 deletions linera-bridge/src/monitor/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ impl BridgeDb {
sqlx::query(
"CREATE TABLE IF NOT EXISTS pending_burns (
linera_height INTEGER NOT NULL,
event_index INTEGER NOT NULL,
block_hash TEXT NOT NULL,
tx_index INTEGER NOT NULL,
event_pos_in_tx INTEGER NOT NULL,
event_index INTEGER NOT NULL,
evm_recipient TEXT NOT NULL,
amount TEXT NOT NULL,
raw_cert BLOB,
Expand All @@ -114,7 +117,10 @@ impl BridgeDb {
sqlx::query(
"CREATE TABLE IF NOT EXISTS finished_burns (
linera_height INTEGER NOT NULL,
event_index INTEGER NOT NULL,
block_hash TEXT NOT NULL,
tx_index INTEGER NOT NULL,
event_pos_in_tx INTEGER NOT NULL,
event_index INTEGER NOT NULL,
evm_recipient TEXT NOT NULL,
amount TEXT NOT NULL,
raw_cert BLOB,
Expand Down Expand Up @@ -217,10 +223,14 @@ impl BridgeDb {
/// Inserts a new pending burn. Ignores duplicates (idempotent).
pub async fn insert_burn(&self, burn: &PendingBurn) -> Result<()> {
sqlx::query(
"INSERT OR IGNORE INTO pending_burns (linera_height, event_index, evm_recipient, amount)
VALUES (?, ?, ?, ?)",
"INSERT OR IGNORE INTO pending_burns
(linera_height, block_hash, tx_index, event_pos_in_tx, event_index, evm_recipient, amount)
VALUES (?, ?, ?, ?, ?, ?, ?)",
)
.bind(burn.height.0 as i64)
.bind(burn.block_hash.to_string())
.bind(burn.tx_index as i64)
.bind(burn.event_pos_in_tx as i64)
.bind(burn.event_index as i64)
.bind(format!("{:#x}", burn.evm_recipient))
.bind(burn.amount.to_string())
Expand All @@ -244,10 +254,10 @@ impl BridgeDb {
let mut tx = self.pool.begin().await?;
let inserted = sqlx::query(
"INSERT OR IGNORE INTO finished_burns
(linera_height, event_index, evm_recipient, amount, raw_cert,
status, created_at)
SELECT linera_height, event_index, evm_recipient, amount, raw_cert,
?, created_at
(linera_height, block_hash, tx_index, event_pos_in_tx, event_index,
evm_recipient, amount, raw_cert, status, created_at)
SELECT linera_height, block_hash, tx_index, event_pos_in_tx, event_index,
evm_recipient, amount, raw_cert, ?, created_at
FROM pending_burns
WHERE linera_height = ? AND event_index = ?",
)
Expand Down Expand Up @@ -321,7 +331,7 @@ impl BridgeDb {
/// in-memory `MonitorState`.
pub async fn load_pending_burns(&self) -> Result<Vec<PendingBurn>> {
let rows = sqlx::query(
"SELECT linera_height, event_index, evm_recipient, amount
"SELECT linera_height, block_hash, tx_index, event_pos_in_tx, event_index, evm_recipient, amount
FROM pending_burns",
)
.fetch_all(&self.pool)
Expand All @@ -330,12 +340,20 @@ impl BridgeDb {
let mut out = Vec::with_capacity(rows.len());
for row in rows {
let height: i64 = row.get(0);
let event_index: i64 = row.get(1);
let evm_recipient: String = row.get(2);
let amount: String = row.get(3);
let block_hash: String = row.get(1);
let tx_index: i64 = row.get(2);
let event_pos_in_tx: i64 = row.get(3);
let event_index: i64 = row.get(4);
let evm_recipient: String = row.get(5);
let amount: String = row.get(6);

out.push(PendingBurn {
height: BlockHeight(height as u64),
block_hash: block_hash
.parse()
.context("invalid block_hash in burns row")?,
tx_index: tx_index as u32,
event_pos_in_tx: event_pos_in_tx as u32,
event_index: event_index as u32,
evm_recipient: evm_recipient
.parse()
Expand Down Expand Up @@ -382,7 +400,7 @@ mod tests {
use std::sync::atomic::{AtomicU32, Ordering};

use alloy::primitives::{Address, B256, U256};
use linera_base::data_types::Amount;
use linera_base::{crypto::CryptoHash, data_types::Amount};
use test_case::test_case;

use super::*;
Expand Down Expand Up @@ -422,6 +440,9 @@ mod tests {
fn test_burn() -> PendingBurn {
PendingBurn {
height: BlockHeight(100),
block_hash: CryptoHash::from([0u8; 32]),
tx_index: 0,
event_pos_in_tx: 0,
event_index: 0,
evm_recipient: "0xabcdef1234567890abcdef1234567890abcdef12"
.parse()
Expand Down
18 changes: 11 additions & 7 deletions linera-bridge/src/monitor/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ pub(crate) async fn process_pending_deposits<E: linera_core::environment::Enviro
log_index,
};
if let Ok(raw) = bcs::to_bytes(&op) {
if let Err(e) = db.store_deposit_raw(&pending.key, &raw).await {
tracing::warn!(%tx_hash, "Failed to store deposit raw bytes: {e:#}");
if let Err(error) = db.store_deposit_raw(&pending.key, &raw).await {
tracing::warn!(%tx_hash, ?error, "Failed to store deposit raw bytes");
}
}
}
Expand All @@ -111,12 +111,16 @@ pub(crate) async fn process_pending_deposits<E: linera_core::environment::Enviro
}
}
}
Err(e) => {
tracing::warn!(%tx_hash, "Proof generation failed: {e:#}");
Err(error) => {
tracing::warn!(%tx_hash, ?error, "Proof generation failed");
}
}

monitor.write().await.mark_deposit_retried(&pending.key);
monitor
.write()
.await
.mark_deposit_retried(&pending.key, max_retries)
.await;
}
}

Expand Down Expand Up @@ -163,8 +167,8 @@ async fn evm_scan_iteration(
};
let deposit = match parse_deposit_event(&receipt_log, bridge_addr) {
Ok(d) => d,
Err(e) => {
tracing::warn!(%tx_hash, "Failed to parse DepositInitiated log: {e:#}");
Err(error) => {
tracing::warn!(%tx_hash, ?error, "Failed to parse DepositInitiated log");
continue;
}
};
Expand Down
Loading
Loading