Skip to content

Commit

Permalink
Release v0.5.4 (#1328)
Browse files Browse the repository at this point in the history
* only spawn_blocking for nonce search (#1321)

* Use spawn_blocking in bitcoin service not in tx builders (#1324)

* Use spawn_blocking in bitcoin service not in tx builders

* Clone outside of spawn

---------

Co-authored-by: yaziciahmet <[email protected]>

* fix bugs regarding tx gas limit (#1323)

* fix bugs regarding tx gas limit

* group gas limit capping functionality to a function

* prepare v0.5.4 (#1327)

* update version number in doc and update changelog

* update neglected CITREA_VERSION constant

---------

Co-authored-by: Ahmet Yazıcı <[email protected]>
Co-authored-by: Roman <[email protected]>
Co-authored-by: yaziciahmet <[email protected]>
  • Loading branch information
4 people authored Oct 11, 2024
1 parent d5211cb commit 4ad1200
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 118 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v0.5.4 (2024-10-11)
- Fixed gas estimation for when a tx has gas limit < block gas limit but with the L1 fee overhead the gas estimation is returned > block gas limit. Preventing transactions from landing on chain. ([#1323](https://github.com/chainwayxyz/citrea/pull/1323))
- Better use of `tokio::spawn_blocking` in Bitcoin DA adapter. ([#1321](https://github.com/chainwayxyz/citrea/pull/1321) [#1324](https://github.com/chainwayxyz/citrea/pull/1324))

## v0.5.3 (2024-10-10)
- `eth_call` RPC now supports state and block overrides. ([#1270](https://github.com/chainwayxyz/citrea/pull/1270))
- `eth_call`, `eth_estimateGas` and `eth_createAccessList` RPCs now supports "pending" block tag. ([#1303](https://github.com/chainwayxyz/citrea/pull/1303))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,27 @@ impl TxListWithReveal for BatchProvingTxs {
#[instrument(level = "trace", skip_all, err)]
pub fn create_seqcommitment_transactions(
body: Vec<u8>,
da_private_key: &SecretKey,
da_private_key: SecretKey,
prev_utxo: Option<UTXO>,
utxos: Vec<UTXO>,
change_address: Address,
reveal_value: u64,
commit_fee_rate: u64,
reveal_fee_rate: u64,
network: Network,
reveal_tx_prefix: &[u8],
reveal_tx_prefix: Vec<u8>,
) -> Result<BatchProvingTxs, anyhow::Error> {
create_batchproof_type_0(
body,
da_private_key,
&da_private_key,
prev_utxo,
utxos,
change_address,
reveal_value,
commit_fee_rate,
reveal_fee_rate,
network,
reveal_tx_prefix,
&reveal_tx_prefix,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,41 +87,41 @@ impl TxListWithReveal for LightClientTxs {
#[instrument(level = "trace", skip_all, err)]
pub fn create_zkproof_transactions(
body: Vec<u8>,
da_private_key: &SecretKey,
da_private_key: SecretKey,
prev_utxo: Option<UTXO>,
utxos: Vec<UTXO>,
change_address: Address,
reveal_value: u64,
commit_fee_rate: u64,
reveal_fee_rate: u64,
network: Network,
reveal_tx_prefix: &[u8],
reveal_tx_prefix: Vec<u8>,
) -> Result<LightClientTxs, anyhow::Error> {
if body.len() < MAX_TXBODY_SIZE {
create_inscription_type_0(
body,
da_private_key,
&da_private_key,
prev_utxo,
utxos,
change_address,
reveal_value,
commit_fee_rate,
reveal_fee_rate,
network,
reveal_tx_prefix,
&reveal_tx_prefix,
)
} else {
create_inscription_type_1(
body,
da_private_key,
&da_private_key,
prev_utxo,
utxos,
change_address,
reveal_value,
commit_fee_rate,
reveal_fee_rate,
network,
reveal_tx_prefix,
&reveal_tx_prefix,
)
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/bitcoin-da/src/helpers/builders/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ fn build_reveal_transaction() {
assert!(tx.is_err());
assert_eq!(format!("{}", tx.unwrap_err()), "input UTXO not big enough");
}

#[test]
fn create_inscription_transactions() {
let (body, address, utxos) = get_mock_data();
Expand All @@ -465,15 +466,15 @@ fn create_inscription_transactions() {
let LightClientTxs::Complete { commit, reveal } =
super::light_client_proof_namespace::create_zkproof_transactions(
body.clone(),
&da_private_key,
da_private_key,
None,
utxos.clone(),
address.clone(),
546,
12,
10,
bitcoin::Network::Bitcoin,
tx_prefix,
tx_prefix.to_vec(),
)
.unwrap()
else {
Expand Down
207 changes: 107 additions & 100 deletions crates/bitcoin-da/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,92 +183,85 @@ impl BitcoinService {
self: Arc<Self>,
mut rx: UnboundedReceiver<Option<SenderWithNotifier<TxidWrapper>>>,
) {
// This should be spawn_blocking, since it is a CPU-bound worker.
// When spawned with tokio::spawn, it blocks other futures and
// disrupts tokio runtime.
tokio::task::spawn_blocking(|| {
tokio::runtime::Handle::current().block_on(async move {
let mut prev_utxo = match self.get_prev_utxo().await {
Ok(Some(prev_utxo)) => Some(prev_utxo),
Ok(None) => {
info!("No pending transactions found");
None
}
Err(e) => {
error!(?e, "Failed to get pending transactions");
None
}
};
tokio::spawn(async move {
let mut prev_utxo = match self.get_prev_utxo().await {
Ok(Some(prev_utxo)) => Some(prev_utxo),
Ok(None) => {
info!("No pending transactions found");
None
}
Err(e) => {
error!(?e, "Failed to get pending transactions");
None
}
};

trace!("BitcoinDA queue is initialized. Waiting for the first request...");

loop {
select! {
request_opt = rx.recv() => {
if let Some(request_opt) = request_opt {
match request_opt {
Some(request) => {
trace!("A new request is received");
let prev = prev_utxo.take();
loop {
// Build and send tx with retries:
let fee_sat_per_vbyte = match self.get_fee_rate().await {
Ok(rate) => rate,
Err(e) => {
error!(?e, "Failed to call get_fee_rate. Retrying...");
tokio::time::sleep(Duration::from_secs(1)).await;
continue;
}
};
match self
.send_transaction_with_fee_rate(
prev.clone(),
request.da_data.clone(),
fee_sat_per_vbyte,
)
.await
{
Ok(tx) => {
let tx_id = TxidWrapper(tx.id);
info!(%tx.id, "Sent tx to BitcoinDA");
prev_utxo = Some(UTXO {
tx_id: tx.id,
vout: 0,
script_pubkey: tx.tx.output[0].script_pubkey.to_hex_string(),
address: None,
amount: tx.tx.output[0].value.to_sat(),
confirmations: 0,
spendable: true,
solvable: true,
});

let _ = request.notify.send(Ok(tx_id));
}
Err(e) => {
error!(?e, "Failed to send transaction to DA layer");
tokio::time::sleep(Duration::from_secs(1)).await;
continue;
}
trace!("BitcoinDA queue is initialized. Waiting for the first request...");

loop {
select! {
request_opt = rx.recv() => {
if let Some(request_opt) = request_opt {
match request_opt {
Some(request) => {
trace!("A new request is received");
let prev = prev_utxo.take();
loop {
// Build and send tx with retries:
let fee_sat_per_vbyte = match self.get_fee_rate().await {
Ok(rate) => rate,
Err(e) => {
error!(?e, "Failed to call get_fee_rate. Retrying...");
tokio::time::sleep(Duration::from_secs(1)).await;
continue;
}
};
match self
.send_transaction_with_fee_rate(
prev.clone(),
request.da_data.clone(),
fee_sat_per_vbyte,
)
.await
{
Ok(tx) => {
let tx_id = TxidWrapper(tx.id);
info!(%tx.id, "Sent tx to BitcoinDA");
prev_utxo = Some(UTXO {
tx_id: tx.id,
vout: 0,
script_pubkey: tx.tx.output[0].script_pubkey.to_hex_string(),
address: None,
amount: tx.tx.output[0].value.to_sat(),
confirmations: 0,
spendable: true,
solvable: true,
});

let _ = request.notify.send(Ok(tx_id));
}
Err(e) => {
error!(?e, "Failed to send transaction to DA layer");
tokio::time::sleep(Duration::from_secs(1)).await;
continue;
}
break;
}
}

None => {
info!("Shutdown signal received. Stopping BitcoinDA queue.");
break;
}
}

None => {
info!("Shutdown signal received. Stopping BitcoinDA queue.");
break;
}
}
},
_ = signal::ctrl_c() => {
return;
}
},
_ = signal::ctrl_c() => {
return;
}
}
});

error!("BitcoinDA queue stopped");
}
});
}

Expand Down Expand Up @@ -374,19 +367,26 @@ impl BitcoinService {
let data = DaDataLightClient::ZKProof(zkproof);
let blob = borsh::to_vec(&data).expect("DaDataLightClient serialize must not fail");
let blob = compress_blob(&blob);

let reveal_light_client_prefix = self.reveal_light_client_prefix.clone();
// create inscribe transactions
let inscription_txs = create_zkproof_transactions(
blob,
&da_private_key,
prev_utxo,
utxos,
address,
REVEAL_OUTPUT_AMOUNT,
fee_sat_per_vbyte,
fee_sat_per_vbyte,
network,
&self.reveal_light_client_prefix,
)?;
let inscription_txs = tokio::task::spawn_blocking(move || {
// Since this is CPU bound work, we use spawn_blocking
// to release the tokio runtime execution
create_zkproof_transactions(
blob,
da_private_key,
prev_utxo,
utxos,
address,
REVEAL_OUTPUT_AMOUNT,
fee_sat_per_vbyte,
fee_sat_per_vbyte,
network,
reveal_light_client_prefix,
)
})
.await??;

// write txs to file, it can be used to continue revealing blob if something goes wrong
inscription_txs.write_to_file(self.tx_backup_dir.clone())?;
Expand All @@ -409,19 +409,26 @@ impl BitcoinService {
DaData::SequencerCommitment(comm) => {
let data = DaDataBatchProof::SequencerCommitment(comm);
let blob = borsh::to_vec(&data).expect("DaDataBatchProof serialize must not fail");

let reveal_batch_prover_prefix = self.reveal_batch_prover_prefix.clone();
// create inscribe transactions
let inscription_txs = create_seqcommitment_transactions(
blob,
&da_private_key,
prev_utxo,
utxos,
address,
REVEAL_OUTPUT_AMOUNT,
fee_sat_per_vbyte,
fee_sat_per_vbyte,
network,
&self.reveal_batch_prover_prefix,
)?;
let inscription_txs = tokio::task::spawn_blocking(move || {
// Since this is CPU bound work, we use spawn_blocking
// to release the tokio runtime execution
create_seqcommitment_transactions(
blob,
da_private_key,
prev_utxo,
utxos,
address,
REVEAL_OUTPUT_AMOUNT,
fee_sat_per_vbyte,
fee_sat_per_vbyte,
network,
reveal_batch_prover_prefix,
)
})
.await??;

// write txs to file, it can be used to continue revealing blob if something goes wrong
inscription_txs.write_to_file(self.tx_backup_dir.clone())?;
Expand Down
Loading

0 comments on commit 4ad1200

Please sign in to comment.