diff --git a/processor/scanner/src/eventuality/mod.rs b/processor/scanner/src/eventuality/mod.rs index 4f5fbe63..20e24112 100644 --- a/processor/scanner/src/eventuality/mod.rs +++ b/processor/scanner/src/eventuality/mod.rs @@ -8,7 +8,7 @@ use primitives::{task::ContinuallyRan, OutputType, ReceivedOutput, Eventuality, use crate::{ lifetime::LifetimeStage, db::{OutputWithInInstruction, ReceiverScanData, ScannerDb, ScanToEventualityDb}, - BlockExt, ScannerFeed, KeyFor, SchedulerUpdate, Scheduler, + BlockExt, ScannerFeed, KeyFor, SchedulerUpdate, Scheduler, sort_outputs, }; mod db; @@ -214,8 +214,11 @@ impl> ContinuallyRan for EventualityTas } // TODO: This also has to intake Burns - let new_eventualities = - self.scheduler.update(&mut txn, SchedulerUpdate { outputs, forwards, returns }); + let mut scheduler_update = SchedulerUpdate { outputs, forwards, returns }; + scheduler_update.outputs.sort_by(sort_outputs); + scheduler_update.forwards.sort_by(sort_outputs); + scheduler_update.returns.sort_by(|a, b| sort_outputs(&a.output, &b.output)); + let new_eventualities = self.scheduler.update(&mut txn, scheduler_update); for (key, new_eventualities) in new_eventualities { let key = { let mut key_repr = as GroupEncoding>::Repr::default(); diff --git a/processor/scanner/src/lib.rs b/processor/scanner/src/lib.rs index ef295471..d245e255 100644 --- a/processor/scanner/src/lib.rs +++ b/processor/scanner/src/lib.rs @@ -1,11 +1,13 @@ use core::{marker::PhantomData, fmt::Debug}; use std::collections::HashMap; +use group::GroupEncoding; + use serai_db::{Get, DbTxn}; use serai_primitives::{NetworkId, Coin, Amount}; -use primitives::{task::*, ReceivedOutput, Block}; +use primitives::{task::*, Address, ReceivedOutput, Block}; // Logic for deciding where in its lifetime a multisig is. mod lifetime; @@ -21,6 +23,16 @@ mod eventuality; /// Task which reports `Batch`s to Substrate. mod report; +pub(crate) fn sort_outputs>( + a: &O, + b: &O, +) -> core::cmp::Ordering { + use core::cmp::{Ordering, Ord}; + let res = a.id().as_ref().cmp(b.id().as_ref()); + assert!(res != Ordering::Equal, "two outputs within a collection had the same ID"); + res +} + /// Extension traits around Block. pub(crate) trait BlockExt: Block { fn scan_for_outputs(&self, key: Self::Key) -> Vec; @@ -28,12 +40,7 @@ pub(crate) trait BlockExt: Block { impl BlockExt for B { fn scan_for_outputs(&self, key: Self::Key) -> Vec { let mut outputs = self.scan_for_outputs_unordered(key); - outputs.sort_by(|a, b| { - use core::cmp::{Ordering, Ord}; - let res = a.id().as_ref().cmp(b.id().as_ref()); - assert!(res != Ordering::Equal, "scanned two outputs within a block with the same ID"); - res - }); + outputs.sort_by(sort_outputs); outputs } } diff --git a/processor/scanner/src/scan.rs b/processor/scanner/src/scan.rs index 861a9725..8617ec18 100644 --- a/processor/scanner/src/scan.rs +++ b/processor/scanner/src/scan.rs @@ -6,13 +6,13 @@ use serai_in_instructions_primitives::{ Shorthand, RefundableInInstruction, InInstruction, InInstructionWithBalance, }; -use primitives::{OutputType, ReceivedOutput, Block}; +use primitives::{task::ContinuallyRan, OutputType, ReceivedOutput, Block}; // TODO: Localize to ScanDb? use crate::{ lifetime::LifetimeStage, db::{OutputWithInInstruction, SenderScanData, ScannerDb, ScanToReportDb, ScanToEventualityDb}, - BlockExt, ScannerFeed, AddressFor, OutputFor, Return, ContinuallyRan, + BlockExt, ScannerFeed, AddressFor, OutputFor, Return, sort_outputs, }; // Construct an InInstruction from an external output. @@ -96,15 +96,8 @@ impl ContinuallyRan for ScanForOutputsTask { let queued_outputs = { let mut queued_outputs = ScannerDb::::take_queued_outputs(&mut txn, b); - // Sort the queued outputs in case they weren't queued in a deterministic fashion - queued_outputs.sort_by(|a, b| { - use core::cmp::{Ordering, Ord}; - let res = a.output.id().as_ref().cmp(b.output.id().as_ref()); - assert!(res != Ordering::Equal); - res - }); - + queued_outputs.sort_by(|a, b| sort_outputs(&a.output, &b.output)); queued_outputs }; for queued_output in queued_outputs {