mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-08-01 12:33:24 +00:00
fix(sequencer): resubmit orphaned tx which comes only after final tip
This commit is contained in:
parent
9d9b75d42f
commit
3d009acb9c
@ -1162,12 +1162,6 @@ fn apply_follow_update(
|
||||
let (resubmit_txs, outcome) = {
|
||||
let mut chain = chain.lock().expect("chain state mutex poisoned");
|
||||
|
||||
// User txs of orphaned blocks, returned to the mempool below.
|
||||
let resubmit_txs: Vec<LeeTransaction> = orphaned
|
||||
.iter()
|
||||
.flat_map(|(_, block)| resubmittable_txs(block))
|
||||
.collect();
|
||||
|
||||
// Outcomes align with `adopted`.
|
||||
let outcomes = chain.apply_channel_update(&orphaned, &adopted);
|
||||
let mut to_persist: Vec<(&Block, bool)> = adopted
|
||||
@ -1201,6 +1195,22 @@ fn apply_follow_update(
|
||||
AcceptOutcome::Parked(_) | AcceptOutcome::RetryableFailure(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
// User txs of orphaned blocks, returned to the mempool below.
|
||||
//
|
||||
// Computed after the finalized tier has advanced, and only for blocks
|
||||
// above it: the zone-sdk reports a block as orphaned once LIB pruning
|
||||
// drops its inscription from the channel lineage, so every block of
|
||||
// ours is orphaned a poll or two after it finalizes. Those transactions
|
||||
// are irreversibly included, and returning them to the mempool puts
|
||||
// them back in every block we produce from then on.
|
||||
let final_height = chain.final_tip().map(|tip| tip.block_id);
|
||||
let resubmit_txs: Vec<LeeTransaction> = orphaned
|
||||
.iter()
|
||||
.filter(|(_, block)| final_height.is_none_or(|id| block.header.block_id > id))
|
||||
.flat_map(|(_, block)| resubmittable_txs(block))
|
||||
.collect();
|
||||
|
||||
// Snapshot the advanced final tier so a restart re-anchors on it.
|
||||
let final_meta = final_advanced.then(|| {
|
||||
let tip = chain.final_tip().expect("advanced final tier has a tip");
|
||||
|
||||
@ -2172,6 +2172,68 @@ async fn follow_orphan_reverts_head_and_requeues_user_txs() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn follow_orphan_of_a_finalized_block_requeues_nothing() {
|
||||
// The zone-sdk reports a block as orphaned once LIB pruning drops its
|
||||
// inscription from the channel lineage, which happens a poll or two after
|
||||
// every block of ours finalizes. Its transactions are irreversibly
|
||||
// included, so requeueing them would put them back in every block we
|
||||
// produce from then on.
|
||||
let config = setup_sequencer_config();
|
||||
let (mut sequencer, mempool_handle) =
|
||||
SequencerCoreWithMockClients::start_from_config(config).await;
|
||||
|
||||
let acc1 = initial_public_user_accounts()[0].account_id;
|
||||
let acc2 = initial_public_user_accounts()[1].account_id;
|
||||
let tx = common::test_utils::create_transaction_native_token_transfer(
|
||||
acc1,
|
||||
0,
|
||||
acc2,
|
||||
10,
|
||||
&create_signing_key_for_account1(),
|
||||
);
|
||||
mempool_handle
|
||||
.push((TransactionOrigin::User, tx))
|
||||
.await
|
||||
.unwrap();
|
||||
sequencer.produce_new_block().await.unwrap();
|
||||
let block2 = sequencer.store.get_block_at_id(2).unwrap().unwrap();
|
||||
|
||||
apply_follow_update(
|
||||
&sequencer.store.dbio(),
|
||||
&sequencer.chain(),
|
||||
&mempool_handle,
|
||||
FollowUpdate {
|
||||
finalized: vec![(MsgId::from(block2.header.hash.0), block2.clone())],
|
||||
..empty_follow_update()
|
||||
},
|
||||
);
|
||||
apply_follow_update(
|
||||
&sequencer.store.dbio(),
|
||||
&sequencer.chain(),
|
||||
&mempool_handle,
|
||||
FollowUpdate {
|
||||
orphaned: vec![(MsgId::from(block2.header.hash.0), block2)],
|
||||
..empty_follow_update()
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sequencer.chain_height(),
|
||||
2,
|
||||
"an irreversible block cannot be reverted"
|
||||
);
|
||||
assert_eq!(
|
||||
sequencer.with_state(|s| s.get_account_by_id(acc2).balance),
|
||||
20010,
|
||||
"the finalized transfer stands"
|
||||
);
|
||||
assert!(
|
||||
sequencer.mempool.pop().is_none(),
|
||||
"a transaction that is already irreversible must not be requeued"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn follow_finalized_own_block_moves_final_tier_and_marks_store() {
|
||||
let config = setup_sequencer_config();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user