Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions fault-proof/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ pub struct ProposerConfig {

/// Optional path to backup file for persisting proposer state across restarts.
pub backup_path: Option<PathBuf>,

/// Maximum time (in seconds) to wait for an L1 transaction submitted by the proposer to
/// reach the required number of confirmations before the watcher gives up. Setting this
/// too low risks declaring "confirmation timeout" on transactions that actually land on
/// chain, which can produce duplicate sibling games on retry. Defaults to 180 to leave
/// comfortable headroom for mempool inclusion plus the configured confirmation depth.
pub tx_confirmation_timeout: u64,
}

/// Helper function to parse a comma-separated list of addresses
Expand Down Expand Up @@ -139,6 +146,9 @@ impl ProposerConfig {
.parse()?,
proof_provider: ProofProviderConfig::from_env()?,
backup_path: env::var("BACKUP_PATH").ok().map(PathBuf::from),
tx_confirmation_timeout: env::var("TX_CONFIRMATION_TIMEOUT")
.unwrap_or("180".to_string())
.parse()?,
})
}

Expand Down Expand Up @@ -175,6 +185,7 @@ impl ProposerConfig {
min_auction_period = self.proof_provider.min_auction_period,
whitelist = ?self.proof_provider.whitelist,
backup_path = ?self.backup_path,
tx_confirmation_timeout = self.tx_confirmation_timeout,
"Proposer configuration loaded"
);
}
Expand Down
24 changes: 20 additions & 4 deletions fault-proof/src/proposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,11 @@ where
let transaction_request = game.prove(agg_proof.bytes().into()).into_transaction_request();
let receipt = self
.signer
.send_transaction_request(self.config.l1_rpc.clone(), transaction_request)
.send_transaction_request_with_timeout(
self.config.l1_rpc.clone(),
transaction_request,
self.config.tx_confirmation_timeout,
)
.await?;

if !receipt.status() {
Expand Down Expand Up @@ -1181,7 +1185,11 @@ where

let receipt = self
.signer
.send_transaction_request(self.config.l1_rpc.clone(), transaction_request)
.send_transaction_request_with_timeout(
self.config.l1_rpc.clone(),
transaction_request,
self.config.tx_confirmation_timeout,
)
.await?;

if !receipt.status() {
Expand Down Expand Up @@ -1311,7 +1319,11 @@ where
let transaction_request = contract.resolve().into_transaction_request();
let receipt = self
.signer
.send_transaction_request(self.config.l1_rpc.clone(), transaction_request)
.send_transaction_request_with_timeout(
self.config.l1_rpc.clone(),
transaction_request,
self.config.tx_confirmation_timeout,
)
.await?;

if !receipt.status() {
Expand All @@ -1337,7 +1349,11 @@ where
contract.claimCredit(self.signer.address()).gas(300_000).into_transaction_request();
let receipt = self
.signer
.send_transaction_request(self.config.l1_rpc.clone(), transaction_request)
.send_transaction_request_with_timeout(
self.config.l1_rpc.clone(),
transaction_request,
self.config.tx_confirmation_timeout,
)
.await?;

if !receipt.status() {
Expand Down
1 change: 1 addition & 0 deletions fault-proof/tests/common/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub async fn new_proposer(
range_split_count: RangeSplitCount::one(),
max_concurrent_range_proofs: NonZero::<usize>::MIN,
backup_path,
tx_confirmation_timeout: 180,
proof_provider: ProofProviderConfig {
timeout: 14400, // 4 hours
network_calls_timeout: 15,
Expand Down
40 changes: 34 additions & 6 deletions utils/signer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,24 @@ impl Signer {
}
}

/// Sends a transaction request, signed by the configured `signer`.
/// Sends a transaction request, signed by the configured `signer`, using the default
/// confirmation timeout of [`TIMEOUT_SECONDS`].
pub async fn send_transaction_request(
&self,
l1_rpc: Url,
transaction_request: TransactionRequest,
) -> Result<TransactionReceipt> {
self.send_transaction_request_with_timeout(l1_rpc, transaction_request, TIMEOUT_SECONDS)
.await
}

/// Sends a transaction request, signed by the configured `signer`, with a caller-supplied
/// confirmation timeout (in seconds).
pub async fn send_transaction_request_with_timeout(
&self,
l1_rpc: Url,
mut transaction_request: TransactionRequest,
timeout_secs: u64,
) -> Result<TransactionReceipt> {
match self {
Signer::Web3Signer(signer_url, signer_address) => {
Expand Down Expand Up @@ -126,7 +139,7 @@ impl Signer {
.await
.context("Failed to send transaction")?
.with_required_confirmations(NUM_CONFIRMATIONS)
.with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS)))
.with_timeout(Some(Duration::from_secs(timeout_secs)))
.get_receipt()
.await?;

Expand All @@ -151,7 +164,7 @@ impl Signer {
.await
.context("Failed to send transaction")?
.with_required_confirmations(NUM_CONFIRMATIONS)
.with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS)))
.with_timeout(Some(Duration::from_secs(timeout_secs)))
.get_receipt()
.await?;

Expand All @@ -177,7 +190,7 @@ impl Signer {
.await
.context("Failed to send KMS-signed transaction")?
.with_required_confirmations(NUM_CONFIRMATIONS)
.with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS)))
.with_timeout(Some(Duration::from_secs(timeout_secs)))
.get_receipt()
.await?;

Expand Down Expand Up @@ -212,8 +225,9 @@ impl SignerLock {
self.cached_address
}

/// Sends a transaction request, signed by the configured signer.
/// Transactions are serialized via a Mutex to prevent nonce conflicts.
/// Sends a transaction request, signed by the configured signer, using the default
/// confirmation timeout of [`TIMEOUT_SECONDS`]. Transactions are serialized via a Mutex
/// to prevent nonce conflicts.
pub async fn send_transaction_request(
&self,
l1_rpc: Url,
Expand All @@ -222,6 +236,20 @@ impl SignerLock {
let signer = self.inner.lock().await;
signer.send_transaction_request(l1_rpc, transaction_request).await
}

/// Sends a transaction request with a caller-supplied confirmation timeout (in seconds).
/// Transactions are serialized via a Mutex to prevent nonce conflicts.
pub async fn send_transaction_request_with_timeout(
&self,
l1_rpc: Url,
transaction_request: TransactionRequest,
timeout_secs: u64,
) -> Result<TransactionReceipt> {
let signer = self.inner.lock().await;
signer
.send_transaction_request_with_timeout(l1_rpc, transaction_request, timeout_secs)
.await
}
}

#[cfg(test)]
Expand Down
Loading