diff --git a/subxt/src/backend/unstable/mod.rs b/subxt/src/backend/unstable/mod.rs index e2c8877718..fb1437352d 100644 --- a/subxt/src/backend/unstable/mod.rs +++ b/subxt/src/backend/unstable/mod.rs @@ -437,13 +437,28 @@ impl Backend for UnstableBackend { extrinsic: &[u8], ) -> Result>, Error> { // We care about new and finalized block hashes. + enum SeenBlock { + New(Ref), + Finalized(Vec), + } enum SeenBlockMarker { New, Finalized, } // First, subscribe to all new and finalized block refs. - let mut seen_blocks_sub = self.follow_handle.subscribe().events(); + // - we subscribe to new refs so that when we see `BestChainBlockIncluded`, we + // can try to return a block ref for the best block. + // - we subscribe to finalized refs so that when we see `Finalized`, we can + // guarantee that when we return here, the finalized block we report has been + // reported from chainHead_follow already. + let mut seen_blocks_sub = self.follow_handle.subscribe().events().filter_map(|ev| { + std::future::ready(match ev { + FollowEvent::NewBlock(ev) => Some(SeenBlock::New(ev.block_hash)), + FollowEvent::Finalized(ev) => Some(SeenBlock::Finalized(ev.finalized_block_hashes)), + _ => None, + }) + }); // Then, submit the transaction. let mut tx_progress = self @@ -470,22 +485,23 @@ impl Backend for UnstableBackend { // Make a note of new or finalized blocks that have come in since we started the TX. if let Poll::Ready(Some(seen_block)) = seen_blocks_sub.poll_next_unpin(cx) { match seen_block { - FollowEvent::NewBlock(new_block) => { - seen_blocks.insert( - new_block.block_hash.hash(), - (SeenBlockMarker::New, new_block.block_hash), - ); + SeenBlock::New(block_ref) => { + // Optimization: once we have a `finalized_hash`, we only care about finalized + // block refs now and can avoid bothering to save new blocks. + if finalized_hash.is_none() { + seen_blocks + .insert(block_ref.hash(), (SeenBlockMarker::New, block_ref)); + } } - FollowEvent::Finalized(finalized_block) => { - for block_ref in finalized_block.finalized_block_hashes { + SeenBlock::Finalized(block_refs) => { + for block_ref in block_refs { seen_blocks.insert( block_ref.hash(), (SeenBlockMarker::Finalized, block_ref), ); } } - _ => (), - }; + } continue; }