mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-22 18:54:40 +00:00
Add sorts for safety even upon non-determinism
This commit is contained in:
parent
75251f04b4
commit
9cebdf7c68
3 changed files with 23 additions and 20 deletions
|
@ -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<D: Db, S: ScannerFeed, Sch: Scheduler<S>> 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 = <KeyFor<S> as GroupEncoding>::Repr::default();
|
||||
|
|
|
@ -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<K: GroupEncoding, A: Address, O: ReceivedOutput<K, A>>(
|
||||
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<Self::Output>;
|
||||
|
@ -28,12 +40,7 @@ pub(crate) trait BlockExt: Block {
|
|||
impl<B: Block> BlockExt for B {
|
||||
fn scan_for_outputs(&self, key: Self::Key) -> Vec<Self::Output> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<D: Db, S: ScannerFeed> ContinuallyRan for ScanForOutputsTask<D, S> {
|
|||
|
||||
let queued_outputs = {
|
||||
let mut queued_outputs = ScannerDb::<S>::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 {
|
||||
|
|
Loading…
Reference in a new issue