mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Add support for multiple orderings in Provided
Necessary as our Tributary chains needed to agree when a Serai block has occurred, and when a Monero block has occurred. Since those could happen at the same time, some validators may put SeraiBlock before ExternalBlock and vice versa, causing a chain halt. Now they can have distinct ordering queues.
This commit is contained in:
@@ -24,7 +24,7 @@ pub struct ProvidedTransactions<D: Db, T: Transaction> {
|
||||
db: D,
|
||||
genesis: [u8; 32],
|
||||
|
||||
pub(crate) transactions: VecDeque<T>,
|
||||
pub(crate) transactions: HashMap<&'static str, VecDeque<T>>,
|
||||
}
|
||||
|
||||
impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
||||
@@ -36,21 +36,25 @@ impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
||||
}
|
||||
|
||||
pub(crate) fn new(db: D, genesis: [u8; 32]) -> Self {
|
||||
let mut res = ProvidedTransactions { db, genesis, transactions: VecDeque::new() };
|
||||
let mut res = ProvidedTransactions { db, genesis, transactions: HashMap::new() };
|
||||
|
||||
let currently_provided = res.db.get(res.current_provided_key()).unwrap_or(vec![]);
|
||||
let mut i = 0;
|
||||
while i < currently_provided.len() {
|
||||
res.transactions.push_back(
|
||||
T::read::<&[u8]>(
|
||||
&mut res
|
||||
.db
|
||||
.get(res.transaction_key(¤tly_provided[i .. (i + 32)]))
|
||||
.unwrap()
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
let tx = T::read::<&[u8]>(
|
||||
&mut res.db.get(res.transaction_key(¤tly_provided[i .. (i + 32)])).unwrap().as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let TransactionKind::Provided(order) = tx.kind() else {
|
||||
panic!("provided transaction saved to disk wasn't provided");
|
||||
};
|
||||
|
||||
if res.transactions.get(order).is_none() {
|
||||
res.transactions.insert(order, VecDeque::new());
|
||||
}
|
||||
res.transactions.get_mut(order).unwrap().push_back(tx);
|
||||
|
||||
i += 32;
|
||||
}
|
||||
|
||||
@@ -59,9 +63,9 @@ impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
||||
|
||||
/// Provide a transaction for inclusion in a block.
|
||||
pub(crate) fn provide(&mut self, tx: T) -> Result<(), ProvidedError> {
|
||||
if tx.kind() != TransactionKind::Provided {
|
||||
Err(ProvidedError::NotProvided)?;
|
||||
}
|
||||
let TransactionKind::Provided(order) = tx.kind() else {
|
||||
Err(ProvidedError::NotProvided)?
|
||||
};
|
||||
|
||||
match verify_transaction(&tx, self.genesis, &mut HashMap::new()) {
|
||||
Ok(()) => {}
|
||||
@@ -83,17 +87,39 @@ impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
||||
txn.put(current_provided_key, currently_provided);
|
||||
txn.commit();
|
||||
|
||||
self.transactions.push_back(tx);
|
||||
if self.transactions.get(order).is_none() {
|
||||
self.transactions.insert(order, VecDeque::new());
|
||||
}
|
||||
self.transactions.get_mut(order).unwrap().push_back(tx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Complete a provided transaction, no longer proposing it nor voting for its validity.
|
||||
pub(crate) fn complete(&mut self, txn: &mut D::Transaction<'_>, tx: [u8; 32]) {
|
||||
assert_eq!(self.transactions.pop_front().unwrap().hash(), tx);
|
||||
pub(crate) fn complete(
|
||||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
order: &'static str,
|
||||
tx: [u8; 32],
|
||||
) {
|
||||
assert_eq!(self.transactions.get_mut(order).unwrap().pop_front().unwrap().hash(), tx);
|
||||
|
||||
let current_provided_key = self.current_provided_key();
|
||||
let mut currently_provided = txn.get(¤t_provided_key).unwrap();
|
||||
assert_eq!(¤tly_provided.drain(.. 32).collect::<Vec<_>>(), &tx);
|
||||
|
||||
// Find this TX's hash
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if currently_provided[i .. (i + 32)] == tx {
|
||||
assert_eq!(¤tly_provided.drain(i .. (i + 32)).collect::<Vec<_>>(), &tx);
|
||||
break;
|
||||
}
|
||||
|
||||
i += 32;
|
||||
if i >= currently_provided.len() {
|
||||
panic!("couldn't find completed TX in currently provided");
|
||||
}
|
||||
}
|
||||
|
||||
txn.put(current_provided_key, currently_provided);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user