Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
5294cfd
feat: Cap bitcoin-da fee rate
jfldde Sep 30, 2025
568e852
Revert capping at the FeeService level
jfldde Sep 30, 2025
b7342e0
Handle capping at the run_da_queue level and leverage existing retry …
jfldde Sep 30, 2025
6da2916
Set default value of 15sat/vb
jfldde Sep 30, 2025
48cd30e
Do not try sending tx with capped fee rate
jfldde Sep 30, 2025
65caf04
Lint
jfldde Sep 30, 2025
71cd09c
Merge branch 'nightly' into feat/cap-da-max-fee-rate
jfldde Oct 1, 2025
64b789f
Temporary cap
jfldde Oct 1, 2025
7e4e781
Comment
jfldde Oct 1, 2025
23a4ee8
Rename to avoid confusion with sequencer config
jfldde Oct 2, 2025
eeb202f
DA job service initial implementation with test passing
jfldde Oct 8, 2025
a539c1e
Rm unused file
jfldde Oct 8, 2025
3d7f1c3
Remove dead code
jfldde Oct 8, 2025
3c93173
Fix build
jfldde Oct 8, 2025
5dfd0d4
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 8, 2025
d9f33a9
Index job ids by index
jfldde Oct 8, 2025
d0682f0
Fetch fee rate before right before funding tx
jfldde Oct 8, 2025
bb1525f
Fix lint
jfldde Oct 8, 2025
80b9d8c
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Oct 8, 2025
7c44415
Rethink should_select_new_utxo logic
jfldde Oct 9, 2025
f05d2cd
job RPCs
jfldde Oct 10, 2025
b16bda0
Cleanup
jfldde Oct 10, 2025
635a477
Cleanup database error propagation
jfldde Oct 10, 2025
b16771d
Persistency test
jfldde Oct 13, 2025
57f4233
Cleanup
jfldde Oct 13, 2025
8c3a891
chore: da jobs schema types (#2966)
rakanalh Oct 13, 2025
eef70f6
Fix clippy issues
rakanalh Oct 13, 2025
aaeaa61
Remove job wrapper in RPCs
jfldde Oct 13, 2025
1d582a6
Keep writes atomic
jfldde Oct 13, 2025
7dc9642
Restore as_u8
jfldde Oct 13, 2025
580e6bc
Prevent concurrent access to job service
jfldde Oct 14, 2025
0c3b30c
Cleanup sent txids tracking
jfldde Oct 14, 2025
a9285d5
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 14, 2025
ac4137e
Fix ledgerdb re-use between services
jfldde Oct 14, 2025
c3475d2
Dedup ledgerdb test config
jfldde Oct 14, 2025
a7eb889
Fix utxo selection
jfldde Oct 14, 2025
d7c06ed
Fix lint
jfldde Oct 14, 2025
1955c2b
Protect behind API_KEY
jfldde Oct 14, 2025
aecc8dc
Merge branch 'feat/cap-da-max-fee-rate' into feat/bitcoin-da-job-service
jfldde Oct 15, 2025
1d345e8
Fee cap
jfldde Oct 15, 2025
695769a
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Oct 15, 2025
8c4d6c3
Da job metrics
jfldde Oct 15, 2025
e5f5523
Rename to da_job
jfldde Oct 16, 2025
cb8ba05
Da job id by prover job id index
jfldde Oct 16, 2025
27d97ae
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 16, 2025
76abe0c
feat: DA job rollback (#2984)
rakanalh Oct 16, 2025
3a6323d
Handle finalize_proving_job
jfldde Oct 16, 2025
72e7d12
Remove prints
jfldde Oct 16, 2025
c16aa69
Fix build
jfldde Oct 17, 2025
8d176d2
Lint
jfldde Oct 17, 2025
00af97a
Restore test
jfldde Oct 17, 2025
54fa3e8
Lint
jfldde Oct 17, 2025
ff7b779
Remove RPC todo
jfldde Oct 17, 2025
6b14d8e
Store only txid in SentChunks
jfldde Oct 19, 2025
542e2ab
Cache RawTxData and retrieve proof by id
jfldde Oct 20, 2025
0987fab
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Oct 20, 2025
f248217
Keep DaTxRequest behind native flag
jfldde Oct 20, 2025
5667649
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 22, 2025
d197439
Handle process new job in select loop
jfldde Oct 22, 2025
28504b3
Add e2e test for batch prover restart recovery
jfldde Oct 22, 2025
a12e54b
Fix build
jfldde Oct 22, 2025
06efea6
Handle StoredProof variant for mockda
jfldde Oct 22, 2025
4299a90
Add RPC to get da job id by job id
jfldde Oct 23, 2025
2bf550b
Remove Job wrapper and store DaTxRequest as value instead
jfldde Oct 24, 2025
d9e8ac5
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 24, 2025
30f6444
Lint
jfldde Oct 24, 2025
b75adfa
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 26, 2025
9516eaf
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 28, 2025
46fe7fd
Recover transient error and test
jfldde Oct 28, 2025
1350a3d
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Oct 28, 2025
ce8a04a
Remove da job RPCs from PROTECTED_METHODS
jfldde Nov 5, 2025
3917bb1
Cap list jobs to 100
jfldde Nov 10, 2025
6bed148
Fix array size
jfldde Nov 10, 2025
e1aed6f
Move DaTxRequest out of state_machine
jfldde Nov 10, 2025
89f62b5
Add missing DaJobIdByProvingJobId to LEDGER_TABLES
jfldde Nov 10, 2025
d65ed88
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Nov 10, 2025
e480de7
Dont wait for seqcom txid and add logging
jfldde Nov 10, 2025
a99ac5b
Rename wait_for_existing_da_job
jfldde Nov 10, 2025
6e8b547
Rename RPC with additional ById suffix
jfldde Nov 10, 2025
8077122
Additional documentation for InProgress and Completed status
jfldde Nov 10, 2025
600498c
Don't go through file for test helper method
jfldde Nov 10, 2025
84e05d9
Lint
jfldde Nov 11, 2025
bd0fdb8
Rename SentChunks to SentTxs to better reflect Complete tx tracking
jfldde Nov 11, 2025
d308b7c
Bump max_rebroadcast_attemps for test_queue_da_transactions_oldest_mode
jfldde Nov 11, 2025
c31ef6d
Move recover job logic
jfldde Nov 11, 2025
3405f4a
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Nov 11, 2025
d1130f1
Extract fee validation logic from process_job
jfldde Nov 11, 2025
a8b7768
Fix lint
jfldde Nov 12, 2025
0420599
Steamline transaction recovery
jfldde Nov 12, 2025
b43e023
Get rid of Pending status
jfldde Nov 12, 2025
08ae239
Limit data passed down to get_job_elapsed_time
jfldde Nov 13, 2025
3378dab
refactor: UtxoManager
jfldde Nov 14, 2025
ed542ee
Merge branch 'nightly' into feat/utxo-manager
jfldde Nov 14, 2025
8fc0022
Merge branch 'nightly' into feat/utxo-manager
jfldde Nov 17, 2025
3f1d784
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Dec 9, 2025
84a1e47
Use parking_lot
jfldde Dec 10, 2025
884500c
Remove deadcode
jfldde Dec 10, 2025
dbc3cb6
Renames
jfldde Dec 10, 2025
5c5d0e8
Use UtxoContext consistently
jfldde Dec 16, 2025
9b46a3c
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Dec 16, 2025
643e369
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Dec 16, 2025
9520a10
Merge branch 'feat/utxo-manager' of https://github.com/chainwayxyz/ci…
jfldde Dec 16, 2025
c1a59f8
Merge branch 'nightly' into feat/bitcoin-da-job-service
jfldde Dec 16, 2025
8de4155
Merge branch 'nightly' of https://github.com/chainwayxyz/citrea into …
jfldde Dec 17, 2025
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
6 changes: 6 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions bin/citrea/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ where
matches!(node_type, NodeWithConfig::Sequencer(_))
|| matches!(node_type, NodeWithConfig::BatchProver(_)),
network,
ledger_db.clone(),
)
.await?;

Expand Down
17 changes: 8 additions & 9 deletions bin/citrea/src/rollup/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ use std::time::Duration;

use async_trait::async_trait;
use bitcoin_da::fee::FeeService;
use bitcoin_da::job::rpc::create_rpc_module as create_da_job_rpc_module;
use bitcoin_da::monitoring::MonitoringService;
use bitcoin_da::network_constants::get_network_constants;
use bitcoin_da::rpc::create_rpc_module as create_da_rpc_module;
use bitcoin_da::service::{
network_to_bitcoin_network, BitcoinService, BitcoinServiceConfig, TxidWrapper,
};
use bitcoin_da::service::{network_to_bitcoin_network, BitcoinService, BitcoinServiceConfig};
use bitcoin_da::spec::{BitcoinSpec, RollupParams};
use bitcoin_da::verifier::BitcoinVerifier;
use bitcoincore_rpc::{Auth, Client};
Expand All @@ -30,9 +29,7 @@ use sov_modules_api::default_context::DefaultContext;
use sov_modules_api::{Address, SpecId, Zkvm};
use sov_modules_rollup_blueprint::RollupBlueprint;
use sov_prover_storage_manager::ProverStorageManager;
use sov_rollup_interface::services::da::TxRequestWithNotifier;
use sov_state::ProverStorage;
use tokio::sync::mpsc::unbounded_channel;
use tracing::instrument;

use crate::guests::{
Expand Down Expand Up @@ -85,6 +82,9 @@ impl RollupBlueprint for BitcoinRollup {
let da_methods = create_da_rpc_module(da_service.clone());
rpc_methods.merge(da_methods)?;

let da_methods = create_da_job_rpc_module(da_service.clone());
rpc_methods.merge(da_methods)?;
Comment on lines 85 to +86
Copy link
Member

Choose a reason for hiding this comment

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

should we really separate these two?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure, I liked doing the PR this way but the resulting daJob namespace might be superfluous. I'll merge them


Ok(rpc_methods)
}

Expand All @@ -107,9 +107,8 @@ impl RollupBlueprint for BitcoinRollup {
require_wallet_check: bool,
task_executor: TaskExecutor,
network: Network,
ledger_db: LedgerDB,
) -> Result<Arc<Self::DaService>, anyhow::Error> {
let (tx, rx) = unbounded_channel::<TxRequestWithNotifier<TxidWrapper>>();

let chain_params = RollupParams {
reveal_tx_prefix: REVEAL_TX_PREFIX.to_vec(),
network,
Expand Down Expand Up @@ -155,7 +154,7 @@ impl RollupBlueprint for BitcoinRollup {
monitoring_service,
fee_service,
require_wallet_check,
tx,
ledger_db,
)
.await?,
);
Expand All @@ -167,7 +166,7 @@ impl RollupBlueprint for BitcoinRollup {
service.monitoring.restore().await?;

task_executor.spawn_with_graceful_shutdown_signal(|tk| {
Arc::clone(&service).run_da_queue(rx, block_rx, tk)
Arc::clone(&service).run_da_queue(block_rx, tk)
});
task_executor
.spawn_with_graceful_shutdown_signal(|tk| Arc::clone(&service.monitoring).run(tk));
Expand Down
4 changes: 3 additions & 1 deletion bin/citrea/src/rollup/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ impl RollupBlueprint for MockDemoRollup {
_require_wallet_check: bool,
_task_manager: TaskExecutor,
_network: Network,
ledger_db: LedgerDB,
) -> Result<Arc<Self::DaService>, anyhow::Error> {
Ok(Arc::new(MockDaService::new(
Ok(Arc::new(MockDaService::new_with_ledger_db(
rollup_config.da.sender_address.clone(),
&rollup_config.da.db_path,
ledger_db,
)))
}

Expand Down
2 changes: 2 additions & 0 deletions bin/citrea/src/rollup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint {
rollup_config: &FullNodeConfig<Self::DaConfig>,
require_da_wallet: bool,
network: Network,
ledger_db: LedgerDB,
) -> Result<Dependencies<Self>> {
let task_manager = TaskManager::current();
let da_service = self
Expand All @@ -85,6 +86,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint {
require_da_wallet,
task_manager.executor(),
network,
ledger_db,
)
.await?;
let (l2_block_tx, l2_block_rx) = broadcast::channel(10);
Expand Down
20 changes: 19 additions & 1 deletion bin/citrea/tests/bitcoin/batch_prover_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ async fn basic_prover_test() -> Result<()> {

// // Send the same commitment that was already proven.
// bitcoin_da_service
// .send_transaction_with_fee_rate(
// .send_transaction_and_wait(
// DaTxRequest::SequencerCommitment(commitments.first().unwrap().clone()),
// 1,
// )
Expand Down Expand Up @@ -1561,6 +1561,12 @@ impl TestCase for RetryProvingTest {
.unwrap();
assert_eq!(proving_job.commitments.len(), 4);

let da_job_id = batch_prover
.client
.http_client()
.get_da_job_id_by_job_id(proving_job.id)
.await?;

// retry proving the same job
let new_job_id = batch_prover
.client
Expand All @@ -1569,6 +1575,18 @@ impl TestCase for RetryProvingTest {
.await?;
assert_ne!(new_job_id, proving_job.id, "new job id should be different");

wait_for_prover_job(batch_prover, new_job_id, None).await?;

let retried_da_job_id = batch_prover
.client
.http_client()
.get_da_job_id_by_job_id(new_job_id)
.await?;
assert_ne!(
da_job_id, retried_da_job_id,
"new da job id should be different"
);

// check the commitments of the new proving job
let new_proving_job = wait_for_prover_job(batch_prover, new_job_id, None).await?;
assert_eq!(new_proving_job.commitments.len(), 4);
Expand Down
2 changes: 1 addition & 1 deletion bin/citrea/tests/bitcoin/bitcoin_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ impl TestCase for BitcoinServiceTest {
}
}

#[tokio::test]
#[tokio::test(flavor = "multi_thread")]
async fn test_bitcoin_service() -> Result<()> {
TestCaseRunner::new(BitcoinServiceTest {
task_manager: TaskManager::current(),
Expand Down
178 changes: 89 additions & 89 deletions bin/citrea/tests/bitcoin/bitcoin_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use std::time::Duration;
use anyhow::bail;
use async_trait::async_trait;
use bitcoin::hashes::Hash;
use bitcoin::{Amount, Txid};
use bitcoin::Txid;
use bitcoin_da::monitoring::TxStatus;
use bitcoin_da::rpc::DaRpcClient;
use bitcoincore_rpc::{Client, RpcApi};
use bitcoincore_rpc::RpcApi;
use citrea_batch_prover::rpc::BatchProverRpcClient;
use citrea_e2e::bitcoin::{BitcoinNode, DEFAULT_FINALITY_DEPTH};
use citrea_e2e::config::{BitcoinConfig, TestCaseConfig};
use citrea_e2e::config::TestCaseConfig;
use citrea_e2e::framework::TestFramework;
use citrea_e2e::node::NodeKind;
use citrea_e2e::test_case::{TestCase, TestCaseRunner};
Expand Down Expand Up @@ -491,89 +491,89 @@ async fn test_cpfp_fee_bump() -> Result<()> {
.await
}

struct MinRelayFeeTest;

impl MinRelayFeeTest {
async fn drain_wallet(
&self,
da: &BitcoinNode,
client: &Client,
amount_to_keep: Amount,
) -> Result<()> {
let balance = da.get_balance(None, None).await?;

let amount_to_send = balance - amount_to_keep;

if amount_to_send <= Amount::ZERO {
return Ok(());
}

let drain_address = da.get_new_address(None, None).await?.assume_checked();

client
.send_to_address(
&drain_address,
amount_to_send,
None,
None,
None,
None,
None,
None,
)
.await?;
da.generate(1).await?;

Ok(())
}
}

#[async_trait]
impl TestCase for MinRelayFeeTest {
fn test_config() -> TestCaseConfig {
TestCaseConfig {
with_sequencer: true,
with_batch_prover: false,
..Default::default()
}
}

fn bitcoin_config() -> BitcoinConfig {
BitcoinConfig {
extra_args: vec!["-fallbackfee=0.00001", "-minrelaytxfee=0.00002"],
..Default::default()
}
}

async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
let da = f.bitcoin_nodes.get(0).unwrap();
let sequencer = f.sequencer.as_mut().unwrap();

self.drain_wallet(da, &sequencer.da, Amount::from_sat(8000))
.await?;

let max_l2_blocks_per_commitment = sequencer.max_l2_blocks_per_commitment();

// Generate seqcommitments
for _ in 0..max_l2_blocks_per_commitment {
sequencer.client.send_publish_batch_request().await?;
}

da.wait_mempool_len(2, None).await?;

// Assert that we hit MinRelayFeeNotMet error but recover and end up sending the tx by increasing fee_rate_multiplier
let sequencer_stdout =
std::fs::read_to_string(sequencer.config.base.dir.join("stdout.log"))?;
assert!(sequencer_stdout.contains("MinRelayFeeNotMet"));

Ok(())
}
}

#[tokio::test]
async fn test_min_relay_fee_handling() -> Result<()> {
TestCaseRunner::new(MinRelayFeeTest)
.set_citrea_path(get_citrea_path())
.run()
.await
}
// struct MinRelayFeeTest;

// impl MinRelayFeeTest {
// async fn drain_wallet(
// &self,
// da: &BitcoinNode,
// client: &Client,
// amount_to_keep: Amount,
// ) -> Result<()> {
// let balance = da.get_balance(None, None).await?;

// let amount_to_send = balance - amount_to_keep;

// if amount_to_send <= Amount::ZERO {
// return Ok(());
// }

// let drain_address = da.get_new_address(None, None).await?.assume_checked();

// client
// .send_to_address(
// &drain_address,
// amount_to_send,
// None,
// None,
// None,
// None,
// None,
// None,
// )
// .await?;
// da.generate(1).await?;

// Ok(())
// }
// }

// #[async_trait]
// impl TestCase for MinRelayFeeTest {
// fn test_config() -> TestCaseConfig {
// TestCaseConfig {
// with_sequencer: true,
// with_batch_prover: false,
// ..Default::default()
// }
// }

// fn bitcoin_config() -> BitcoinConfig {
// BitcoinConfig {
// extra_args: vec!["-fallbackfee=0.00001", "-minrelaytxfee=0.00002"],
// ..Default::default()
// }
// }

// async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
// let da = f.bitcoin_nodes.get(0).unwrap();
// let sequencer = f.sequencer.as_mut().unwrap();

// self.drain_wallet(da, &sequencer.da, Amount::from_sat(8000))
// .await?;

// let max_l2_blocks_per_commitment = sequencer.max_l2_blocks_per_commitment();

// // Generate seqcommitments
// for _ in 0..max_l2_blocks_per_commitment {
// sequencer.client.send_publish_batch_request().await?;
// }

// da.wait_mempool_len(2, None).await?;

// // Assert that we hit MinRelayFeeNotMet error but recover and end up sending the tx by increasing fee_rate_multiplier
// let sequencer_stdout =
// std::fs::read_to_string(sequencer.config.base.dir.join("stdout.log"))?;
// assert!(sequencer_stdout.contains("MinRelayFeeNotMet"));

// Ok(())
// }
// }

// #[tokio::test]
// async fn test_min_relay_fee_handling() -> Result<()> {
// TestCaseRunner::new(MinRelayFeeTest)
// .set_citrea_path(get_citrea_path())
// .run()
// .await
// }
2 changes: 1 addition & 1 deletion bin/citrea/tests/bitcoin/bitcoin_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ impl BitcoinVerifierTest {
}
}

#[tokio::test]
#[tokio::test(flavor = "multi_thread")]
async fn test_bitcoin_verifier() -> Result<()> {
TestCaseRunner::new(BitcoinVerifierTest {
task_manager: TaskManager::current(),
Expand Down
Loading
Loading