Skip to content

Commit 435e3f8

Browse files
bewakesBibek Pandey
andauthored
writer: Add retries with exponential backoff when signing fails (#452)
Co-authored-by: Bibek Pandey <[email protected]>
1 parent b7078bd commit 435e3f8

File tree

7 files changed

+48
-16
lines changed

7 files changed

+48
-16
lines changed

crates/btcio/src/writer/builder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use tracing::trace;
3333

3434
use crate::{
3535
rpc::{
36+
error::ClientError,
3637
traits::{Reader, Signer, Wallet},
3738
types::ListUnspent,
3839
},
@@ -51,6 +52,9 @@ pub enum InscriptionError {
5152
#[error("Error building taproot")]
5253
Taproot(#[from] TaprootBuilderError),
5354

55+
#[error("Sign error: {0}")]
56+
SigningFailed(#[from] ClientError),
57+
5458
#[error("{0}")]
5559
Other(#[from] anyhow::Error),
5660
}

crates/btcio/src/writer/signer.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,8 @@ pub async fn create_and_sign_blob_inscriptions(
3333

3434
let ctxid = commit.compute_txid();
3535
debug!(commit_txid = ?ctxid, "Signing commit transaction");
36-
let signed_commit = client
37-
.sign_raw_transaction_with_wallet(&commit)
38-
.await
39-
.expect("could not sign commit tx")
40-
.hex;
41-
42-
let signed_commit: Transaction = consensus::encode::deserialize_hex(&signed_commit)
36+
let signed_tx_raw = client.sign_raw_transaction_with_wallet(&commit).await?.hex;
37+
let signed_commit: Transaction = consensus::encode::deserialize_hex(&signed_tx_raw)
4338
.expect("could not deserialize transaction");
4439
let cid: Buf32 = signed_commit.compute_txid().into();
4540
let rid: Buf32 = reveal.compute_txid().into();

crates/btcio/src/writer/task.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use strata_db::{
44
traits::SequencerDatabase,
55
types::{BlobEntry, BlobL1Status, L1TxStatus},
66
};
7+
use strata_primitives::buf::Buf32;
78
use strata_state::da_blob::{BlobDest, BlobIntent};
89
use strata_status::StatusTx;
910
use strata_storage::ops::inscription::{Context, InscriptionDataOps};
@@ -18,6 +19,9 @@ use crate::{
1819
writer::{builder::InscriptionError, signer::create_and_sign_blob_inscriptions},
1920
};
2021

22+
const SIGN_MAX_RETRIES: u8 = 3;
23+
const BASE_SIGN_DELAY: u64 = 3; // Seconds
24+
2125
/// A handle to the Inscription task.
2226
pub struct InscriptionHandle {
2327
ops: Arc<InscriptionDataOps>,
@@ -130,8 +134,10 @@ fn get_next_blobidx_to_watch(insc_ops: &InscriptionDataOps) -> anyhow::Result<u6
130134
}
131135

132136
/// Watches for inscription transactions status in bitcoin. Note that this watches for each
133-
/// inscription until it is confirmed
134-
/// Watches for inscription transactions status in the Bitcoin blockchain.
137+
/// inscription until it is confirmed.
138+
/// Watches for inscription transactions status in the Bitcoin blockchain. The current design is to
139+
/// watch for inscriptions serially i.e. next inscription is not processed unless the current one is
140+
/// confirmed to bitcoin.
135141
///
136142
/// # Note
137143
///
@@ -159,7 +165,7 @@ pub async fn watcher_task(
159165
// entry
160166
BlobL1Status::Unsigned | BlobL1Status::NeedsResign => {
161167
debug!(?blobentry.status, %curr_blobidx, "Processing unsigned blobentry");
162-
match create_and_sign_blob_inscriptions(
168+
match create_and_sign_blob_inscriptions_with_retries(
163169
&blobentry,
164170
&broadcast_handle,
165171
bitcoin_client.clone(),
@@ -233,6 +239,33 @@ pub async fn watcher_task(
233239
}
234240
}
235241

242+
async fn create_and_sign_blob_inscriptions_with_retries(
243+
blobentry: &BlobEntry,
244+
broadcast_handle: &L1BroadcastHandle,
245+
client: Arc<impl Reader + Wallet + Signer>,
246+
config: &WriterConfig,
247+
) -> Result<(Buf32, Buf32), InscriptionError> {
248+
let mut retries = 0;
249+
let mut delay = BASE_SIGN_DELAY;
250+
while retries <= SIGN_MAX_RETRIES {
251+
match create_and_sign_blob_inscriptions(blobentry, broadcast_handle, client.clone(), config)
252+
.await
253+
{
254+
Ok(d) => return Ok(d),
255+
Err(err) => {
256+
warn!(%err, commit_txid = %blobentry.commit_txid, "Error creating and signing blob, retrying");
257+
}
258+
}
259+
retries += 1;
260+
tokio::time::sleep(Duration::new(delay, 0)).await;
261+
delay <<= 1;
262+
}
263+
error!(commit_txid = %blobentry.commit_txid, "Max retries exceeded while creating and signing blob");
264+
Err(InscriptionError::Other(anyhow::anyhow!(
265+
"Max retries exceeded while creating and signing blob"
266+
)))
267+
}
268+
236269
async fn update_l1_status(
237270
blobentry: &BlobEntry,
238271
new_status: &BlobL1Status,

provers/sp1/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ tracing.workspace = true
3838

3939
[features]
4040
default = ["prover"]
41-
prover = ["dep:strata-sp1-adapter"]
4241
docker-build = []
42+
prover = ["dep:strata-sp1-adapter"]

provers/sp1/guest-checkpoint/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ strata-zkvm = { path = "../../../crates/zkvm/zkvm" }
2222
substrate-bn = { git = "https://github.com/sp1-patches/bn", branch = "patch-v0.7.0" }
2323

2424
[patch.crates-io]
25-
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }
2625
secp256k1 = { git = "https://github.com/sp1-patches/rust-secp256k1", branch = "patch-secp256k1-v0.29.1" }
26+
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }

provers/sp1/guest-evm-ee-stf/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ sp1-zkvm = "2.0.0"
1111
strata-proofimpl-evm-ee-stf = { path = "../../../crates/proof-impl/evm-ee-stf" }
1212

1313
[patch.crates-io]
14-
secp256k1 = { git = "https://github.com/sp1-patches/rust-secp256k1", branch = "patch-secp256k1-v0.29.1" }
15-
tiny-keccak = { git = "https://github.com/sp1-patches/tiny-keccak", branch = "patch-v2.0.2" }
16-
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }
1714
revm = { git = "https://github.com/sp1-patches/revm-new", branch = "john/update-for-v1" }
1815
revm-primitives = { git = "https://github.com/sp1-patches/revm-new", branch = "john/update-for-v1" }
16+
secp256k1 = { git = "https://github.com/sp1-patches/rust-secp256k1", branch = "patch-secp256k1-v0.29.1" }
17+
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }
18+
tiny-keccak = { git = "https://github.com/sp1-patches/tiny-keccak", branch = "patch-v2.0.2" }

provers/sp1/guest-l1-batch/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ strata-state = { path = "../../../crates/state" }
1818
strata-tx-parser = { path = "../../../crates/tx-parser" }
1919

2020
[patch.crates-io]
21-
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }
2221
secp256k1 = { git = "https://github.com/sp1-patches/rust-secp256k1", branch = "patch-secp256k1-v0.29.1" }
22+
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }

0 commit comments

Comments
 (0)