Skip to content

Commit 90da68e

Browse files
authored
fix: 🚑 Avoid cleaning up tx store with genesis block (#589)
* fix: 🐛 Avoid cleaning up tx store with genesis block * fix: 🔊 Use warn instead of error logs for maybe expected failures
1 parent 5fcd335 commit 90da68e

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

client/blockchain-service/src/handler.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,8 +1657,10 @@ where
16571657
// Transactions with a nonce below the on-chain nonce of this block are finalised.
16581658
// Still, we'll delete up to the last finalised block processed, to leave transactions with
16591659
// a terminal state in the pending DB for a short period of time.
1660-
self.cleanup_pending_tx_store(self.last_finalised_block_processed.hash)
1661-
.await;
1660+
if matches!(self.role, MultiInstancesNodeRole::Leader) {
1661+
self.cleanup_pending_tx_store(self.last_finalised_block_processed.hash)
1662+
.await;
1663+
}
16621664

16631665
// Update the last finalised block processed.
16641666
self.last_finalised_block_processed = MinimalBlockInfo {

client/blockchain-service/src/utils.rs

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -478,19 +478,29 @@ where
478478
}
479479

480480
/// Get the current account nonce on-chain for a generic signature type.
481-
pub(crate) fn account_nonce(&self, block_hash: &Runtime::Hash) -> u32 {
481+
pub(crate) fn account_nonce(&self, block_hash: &Runtime::Hash) -> Result<u32> {
482482
let pub_key = Self::caller_pub_key(self.keystore.clone());
483483
self.client
484484
.runtime_api()
485485
.account_nonce(*block_hash, pub_key.into())
486-
.expect("Fetching account nonce works; qed")
486+
.map_err(|e| anyhow!("Fetching account nonce failed: {e}"))
487487
}
488488

489489
/// Checks if the account nonce on-chain is higher than the nonce in the [`BlockchainService`].
490490
///
491491
/// If the nonce is higher, the `nonce_counter` is updated in the [`BlockchainService`].
492492
pub(crate) fn sync_nonce(&mut self, block_hash: &Runtime::Hash) {
493-
let on_chain_nonce = self.account_nonce(block_hash);
493+
let on_chain_nonce = match self.account_nonce(block_hash) {
494+
Ok(nonce) => nonce,
495+
Err(e) => {
496+
error!(
497+
target: LOG_TARGET,
498+
"Failed to sync nonce for block {}: {e}",
499+
block_hash
500+
);
501+
return;
502+
}
503+
};
494504
if on_chain_nonce > self.nonce_counter {
495505
debug!(
496506
target: LOG_TARGET,
@@ -597,7 +607,10 @@ where
597607
let block_number = self.client.info().best_number.saturated_into();
598608

599609
// Check if there's a nonce gap we can fill with this transaction
600-
let on_chain_nonce = self.account_nonce(&block_hash);
610+
let on_chain_nonce = self.account_nonce(&block_hash).map_err(|e| {
611+
error!(target: LOG_TARGET, "Failed to get on-chain nonce while sending extrinsic: {e}");
612+
e
613+
})?;
601614
let gaps =
602615
self.transaction_manager
603616
.detect_gaps(on_chain_nonce, self.nonce_counter, block_number);
@@ -1104,7 +1117,17 @@ where
11041117
block_number: BlockNumber<Runtime>,
11051118
block_hash: Runtime::Hash,
11061119
) {
1107-
let on_chain_nonce = self.account_nonce(&block_hash);
1120+
let on_chain_nonce = match self.account_nonce(&block_hash) {
1121+
Ok(nonce) => nonce,
1122+
Err(e) => {
1123+
warn!(
1124+
target: LOG_TARGET,
1125+
"Failed to get on-chain nonce while cleaning up tx manager at block {}. If this is the genesis block or a sufficiently old block, this is expected and can be ignored: {e}",
1126+
block_hash
1127+
);
1128+
return;
1129+
}
1130+
};
11081131
self.transaction_manager
11091132
.cleanup_stale_nonce_gaps(on_chain_nonce);
11101133

@@ -1116,15 +1139,28 @@ where
11161139
///
11171140
/// Get the on-chain nonce for the given block hash and cleans up all pending transactions below that nonce.
11181141
pub(crate) async fn cleanup_pending_tx_store(&self, block_hash: Runtime::Hash) {
1119-
if matches!(self.role, MultiInstancesNodeRole::Follower) {
1142+
if matches!(
1143+
self.role,
1144+
MultiInstancesNodeRole::Follower | MultiInstancesNodeRole::Standalone
1145+
) {
11201146
error!(
11211147
target: LOG_TARGET,
1122-
"This node is a follower and cannot perform DB cleanup. Only leader or standalone nodes may perform DB cleanup"
1148+
"This node is a follower or standalone and cannot perform DB cleanup. Only leader nodes may perform DB cleanup"
11231149
);
11241150
return;
11251151
}
11261152

1127-
let on_chain_nonce = self.account_nonce(&block_hash);
1153+
let on_chain_nonce = match self.account_nonce(&block_hash) {
1154+
Ok(nonce) => nonce,
1155+
Err(e) => {
1156+
warn!(
1157+
target: LOG_TARGET,
1158+
"Failed to get on-chain nonce while cleaning up pending tx store at block {}. If this is the genesis block or a sufficiently old block, this is expected and can be ignored: {e}",
1159+
block_hash
1160+
);
1161+
return;
1162+
}
1163+
};
11281164

11291165
if let Some(store) = &self.pending_tx_store {
11301166
let caller_pub_key = Self::caller_pub_key(self.keystore.clone());
@@ -1331,7 +1367,17 @@ where
13311367
block_hash: Runtime::Hash,
13321368
) {
13331369
// Detect gaps in the nonce sequence
1334-
let on_chain_nonce = self.account_nonce(&block_hash);
1370+
let on_chain_nonce = match self.account_nonce(&block_hash) {
1371+
Ok(nonce) => nonce,
1372+
Err(e) => {
1373+
warn!(
1374+
target: LOG_TARGET,
1375+
"Failed to get on-chain nonce while handling old nonce gaps at block {}. If this is the genesis block or a sufficiently old block, this is expected and can be ignored: {e}",
1376+
block_hash
1377+
);
1378+
return;
1379+
}
1380+
};
13351381
let gaps =
13361382
self.transaction_manager
13371383
.detect_gaps(on_chain_nonce, self.nonce_counter, block_number);

0 commit comments

Comments
 (0)