Skip to content

Commit bf1e610

Browse files
authored
Merge branch 'develop' into update-changelog-3.0.0
2 parents 51879b9 + bb9077f commit bf1e610

File tree

4 files changed

+116
-12
lines changed

4 files changed

+116
-12
lines changed

stackslib/src/chainstate/nakamoto/miner.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,19 @@ impl BlockBuilder for NakamotoBlockBuilder {
674674
tx.txid(),
675675
100 - TX_BLOCK_LIMIT_PROPORTION_HEURISTIC,
676676
&total_budget
677+
);
678+
let mut measured_cost = cost_after;
679+
let measured_cost = if measured_cost.sub(&cost_before).is_ok() {
680+
Some(measured_cost)
681+
} else {
682+
warn!(
683+
"Failed to compute measured cost of a too big transaction"
677684
);
685+
None
686+
};
678687
return TransactionResult::error(
679688
&tx,
680-
Error::TransactionTooBigError,
689+
Error::TransactionTooBigError(measured_cost),
681690
);
682691
} else {
683692
warn!(

stackslib/src/chainstate/stacks/miner.rs

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,9 +1040,18 @@ impl<'a> StacksMicroblockBuilder<'a> {
10401040
100 - TX_BLOCK_LIMIT_PROPORTION_HEURISTIC,
10411041
&total_budget
10421042
);
1043+
let mut measured_cost = cost_after.clone();
1044+
let measured_cost = if measured_cost.sub(cost_before).is_ok() {
1045+
Some(measured_cost)
1046+
} else {
1047+
warn!(
1048+
"Failed to compute measured cost of a too big transaction"
1049+
);
1050+
None
1051+
};
10431052
return Ok(TransactionResult::error(
10441053
&tx,
1045-
Error::TransactionTooBigError,
1054+
Error::TransactionTooBigError(measured_cost),
10461055
));
10471056
} else {
10481057
warn!(
@@ -1323,7 +1332,22 @@ impl<'a> StacksMicroblockBuilder<'a> {
13231332
return Ok(None);
13241333
}
13251334
}
1326-
Error::TransactionTooBigError => {
1335+
Error::TransactionTooBigError(measured_cost) => {
1336+
if update_estimator {
1337+
if let Some(measured_cost) = measured_cost {
1338+
if let Err(e) = estimator.notify_event(
1339+
&mempool_tx.tx.payload,
1340+
&measured_cost,
1341+
&block_limit,
1342+
&stacks_epoch_id,
1343+
) {
1344+
warn!("Error updating estimator";
1345+
"txid" => %mempool_tx.metadata.txid,
1346+
"error" => ?e);
1347+
}
1348+
}
1349+
}
1350+
13271351
invalidated_txs.push(mempool_tx.metadata.txid);
13281352
}
13291353
_ => {}
@@ -2405,7 +2429,22 @@ impl StacksBlockBuilder {
24052429
return Ok(None);
24062430
}
24072431
}
2408-
Error::TransactionTooBigError => {
2432+
Error::TransactionTooBigError(measured_cost) => {
2433+
if update_estimator {
2434+
if let Some(measured_cost) = measured_cost {
2435+
if let Err(e) = estimator.notify_event(
2436+
&txinfo.tx.payload,
2437+
&measured_cost,
2438+
&block_limit,
2439+
&stacks_epoch_id,
2440+
) {
2441+
warn!("Error updating estimator";
2442+
"txid" => %txinfo.metadata.txid,
2443+
"error" => ?e);
2444+
}
2445+
}
2446+
}
2447+
24092448
invalidated_txs.push(txinfo.metadata.txid);
24102449
}
24112450
Error::InvalidStacksTransaction(_, true) => {
@@ -2714,9 +2753,18 @@ impl BlockBuilder for StacksBlockBuilder {
27142753
100 - TX_BLOCK_LIMIT_PROPORTION_HEURISTIC,
27152754
&total_budget
27162755
);
2756+
let mut measured_cost = cost_after;
2757+
let measured_cost = if measured_cost.sub(&cost_before).is_ok() {
2758+
Some(measured_cost)
2759+
} else {
2760+
warn!(
2761+
"Failed to compute measured cost of a too big transaction"
2762+
);
2763+
None
2764+
};
27172765
return TransactionResult::error(
27182766
&tx,
2719-
Error::TransactionTooBigError,
2767+
Error::TransactionTooBigError(measured_cost),
27202768
);
27212769
} else {
27222770
warn!(
@@ -2795,9 +2843,19 @@ impl BlockBuilder for StacksBlockBuilder {
27952843
100 - TX_BLOCK_LIMIT_PROPORTION_HEURISTIC,
27962844
&total_budget
27972845
);
2846+
let mut measured_cost = cost_after;
2847+
let measured_cost = if measured_cost.sub(&cost_before).is_ok() {
2848+
Some(measured_cost)
2849+
} else {
2850+
warn!(
2851+
"Failed to compute measured cost of a too big transaction"
2852+
);
2853+
None
2854+
};
2855+
27982856
return TransactionResult::error(
27992857
&tx,
2800-
Error::TransactionTooBigError,
2858+
Error::TransactionTooBigError(measured_cost),
28012859
);
28022860
} else {
28032861
warn!(

stackslib/src/chainstate/stacks/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub enum Error {
104104
NotInSameFork,
105105
InvalidChainstateDB,
106106
BlockTooBigError,
107-
TransactionTooBigError,
107+
TransactionTooBigError(Option<ExecutionCost>),
108108
BlockCostExceeded,
109109
NoTransactionsToMine,
110110
MicroblockStreamTooLongError,
@@ -168,7 +168,9 @@ impl fmt::Display for Error {
168168
Error::NoSuchBlockError => write!(f, "No such Stacks block"),
169169
Error::InvalidChainstateDB => write!(f, "Invalid chainstate database"),
170170
Error::BlockTooBigError => write!(f, "Too much data in block"),
171-
Error::TransactionTooBigError => write!(f, "Too much data in transaction"),
171+
Error::TransactionTooBigError(ref c) => {
172+
write!(f, "Too much data in transaction: measured_cost={c:?}")
173+
}
172174
Error::BlockCostExceeded => write!(f, "Block execution budget exceeded"),
173175
Error::MicroblockStreamTooLongError => write!(f, "Too many microblocks in stream"),
174176
Error::IncompatibleSpendingConditionError => {
@@ -246,7 +248,7 @@ impl error::Error for Error {
246248
Error::NoSuchBlockError => None,
247249
Error::InvalidChainstateDB => None,
248250
Error::BlockTooBigError => None,
249-
Error::TransactionTooBigError => None,
251+
Error::TransactionTooBigError(..) => None,
250252
Error::BlockCostExceeded => None,
251253
Error::MicroblockStreamTooLongError => None,
252254
Error::IncompatibleSpendingConditionError => None,
@@ -291,7 +293,7 @@ impl Error {
291293
Error::NoSuchBlockError => "NoSuchBlockError",
292294
Error::InvalidChainstateDB => "InvalidChainstateDB",
293295
Error::BlockTooBigError => "BlockTooBigError",
294-
Error::TransactionTooBigError => "TransactionTooBigError",
296+
Error::TransactionTooBigError(..) => "TransactionTooBigError",
295297
Error::BlockCostExceeded => "BlockCostExceeded",
296298
Error::MicroblockStreamTooLongError => "MicroblockStreamTooLongError",
297299
Error::IncompatibleSpendingConditionError => "IncompatibleSpendingConditionError",

testnet/stacks-node/src/event_dispatcher.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,42 @@ impl EventObserver {
355355
Ok(())
356356
}
357357

358+
/// Insert a payload into the database, retrying on failure.
359+
fn insert_payload_with_retry(
360+
conn: &Connection,
361+
url: &str,
362+
payload: &serde_json::Value,
363+
timeout: Duration,
364+
) {
365+
let mut attempts = 0i64;
366+
let mut backoff = Duration::from_millis(100); // Initial backoff duration
367+
let max_backoff = Duration::from_secs(5); // Cap the backoff duration
368+
369+
loop {
370+
match Self::insert_payload(conn, url, payload, timeout) {
371+
Ok(_) => {
372+
// Successful insert, break the loop
373+
return;
374+
}
375+
Err(err) => {
376+
// Log the error, then retry after a delay
377+
warn!("Failed to insert payload into event observer database: {:?}", err;
378+
"backoff" => ?backoff,
379+
"attempts" => attempts
380+
);
381+
382+
// Wait for the backoff duration
383+
sleep(backoff);
384+
385+
// Increase the backoff duration (with exponential backoff)
386+
backoff = std::cmp::min(backoff.saturating_mul(2), max_backoff);
387+
388+
attempts = attempts.saturating_add(1);
389+
}
390+
}
391+
}
392+
}
393+
358394
fn get_pending_payloads(
359395
conn: &Connection,
360396
) -> Result<Vec<(i64, String, serde_json::Value, u64)>, db_error> {
@@ -524,8 +560,7 @@ impl EventObserver {
524560
Connection::open(db_path).expect("Failed to open database for event observer");
525561

526562
// Insert the new payload into the database
527-
Self::insert_payload(&conn, &full_url, payload, self.timeout)
528-
.expect("Failed to insert payload into event observer database");
563+
Self::insert_payload_with_retry(&conn, &full_url, payload, self.timeout);
529564

530565
// Process all pending payloads
531566
Self::process_pending_payloads(&conn);

0 commit comments

Comments
 (0)