iuna

iuna - experimental devnet protocol
git clone https://iuna.jhx.app/git/iuna.git
Log | Files | Refs | README | LICENSE

ledger_mempool.rs (3690B)


      1 use anyhow::{Result, bail};
      2 
      3 use super::ledger_ops::{
      4     apply_transaction, spend_blinded_inputs, spend_inputs, transaction_has_missing_inputs,
      5 };
      6 use super::transaction::{
      7     BlindedReveal, BlindedTransaction, Transaction, blinded_transaction_inputs_spent_by,
      8     transaction_inputs_spent_by, transaction_inputs_spent_by_inputs,
      9 };
     10 use super::{Ledger, MAX_ORPHAN_TRANSACTIONS, MAX_PENDING_TRANSACTIONS, TransactionSubmitOutcome};
     11 
     12 impl Ledger {
     13     pub fn submit_transaction(&mut self, transaction: Transaction) -> Result<bool> {
     14         Ok(self.submit_transaction_with_outcome(transaction)?.added())
     15     }
     16 
     17     pub(crate) fn reserve_transaction_inputs(&mut self, transaction: &Transaction) -> Result<()> {
     18         self.validate_new_transaction(transaction)?;
     19         let mut utxos = self.utxos.clone();
     20         spend_inputs(transaction, &mut utxos)?;
     21         self.utxos = utxos;
     22         Ok(())
     23     }
     24 
     25     pub fn submit_blinded_transaction(&mut self, transaction: BlindedTransaction) -> Result<bool> {
     26         if self.has_blinded_transaction(&transaction.commitment) {
     27             return Ok(false);
     28         }
     29         self.validate_blinded_transaction(&transaction)?;
     30         if blinded_transaction_inputs_spent_by(&transaction, &self.pending_blinded)
     31             || transaction_inputs_spent_by_inputs(&transaction.inputs, &self.pending)
     32             || transaction_inputs_spent_by_inputs(&transaction.inputs, &self.orphans)
     33         {
     34             bail!("blinded transaction conflicts with pending inputs");
     35         }
     36         let mut utxos = self.utxos_after_valid_pending_and_blinded()?;
     37         spend_blinded_inputs(&transaction, &mut utxos)?;
     38         if self.pending_blinded.len() >= MAX_PENDING_TRANSACTIONS {
     39             bail!("blinded mempool is full");
     40         }
     41         self.pending_blinded.push(transaction);
     42         Ok(true)
     43     }
     44 
     45     pub fn submit_blinded_reveal(&mut self, reveal: BlindedReveal) -> Result<bool> {
     46         if self.has_blinded_reveal(&reveal.commitment) {
     47             return Ok(false);
     48         }
     49         self.validate_blinded_reveal_terms(&reveal)?;
     50         if self.pending_reveals.len() >= MAX_PENDING_TRANSACTIONS {
     51             bail!("blinded reveal pool is full");
     52         }
     53         self.pending_reveals.push(reveal);
     54         Ok(true)
     55     }
     56 
     57     pub fn submit_transaction_with_outcome(
     58         &mut self,
     59         transaction: Transaction,
     60     ) -> Result<TransactionSubmitOutcome> {
     61         if self.has_transaction(transaction.signature()) {
     62             return Ok(TransactionSubmitOutcome::AlreadyKnown);
     63         }
     64 
     65         transaction.verify_signature()?;
     66         self.validate_transaction_terms(&transaction)?;
     67         self.validate_mine_anchor_available(&transaction)?;
     68 
     69         if transaction_inputs_spent_by(&transaction, &self.pending) {
     70             return Ok(TransactionSubmitOutcome::ConflictsWithPending);
     71         }
     72         if transaction_inputs_spent_by(&transaction, &self.orphans) {
     73             return Ok(TransactionSubmitOutcome::ConflictsWithPending);
     74         }
     75 
     76         if self.pending.len() >= MAX_PENDING_TRANSACTIONS {
     77             bail!("mempool is full");
     78         }
     79 
     80         let mut utxos = self.utxos_after_valid_pending_and_blinded()?;
     81         if transaction_has_missing_inputs(&transaction, &utxos) {
     82             if self.orphans.len() >= MAX_ORPHAN_TRANSACTIONS {
     83                 bail!("orphan transaction pool is full");
     84             }
     85             self.orphans.push(transaction);
     86             return Ok(TransactionSubmitOutcome::Added);
     87         }
     88         apply_transaction(&transaction, &mut utxos)?;
     89         self.pending.push(transaction);
     90         self.promote_orphan_transactions()?;
     91         Ok(TransactionSubmitOutcome::Added)
     92     }
     93 }