history.rs (2309B)
1 use std::collections::BTreeMap; 2 3 use anyhow::{Context, Result, bail}; 4 5 use super::blinded::{ 6 ActiveBlindedTransaction, blinded_envelope_fee_for_transaction, decrypt_blinded_transaction, 7 }; 8 use super::{ChainSnapshot, RevealedBlindedTransaction, Transaction}; 9 10 pub fn revealed_blinded_transactions( 11 snapshot: &ChainSnapshot, 12 ) -> Result<Vec<RevealedBlindedTransaction>> { 13 let mut active = BTreeMap::<String, ActiveBlindedTransaction>::new(); 14 let mut revealed = Vec::new(); 15 for block in &snapshot.blocks { 16 for reveal in block.all_blinded_reveals() { 17 let active_transaction = active.get(&reveal.commitment).with_context(|| { 18 format!( 19 "block {} reveals unknown blinded transaction {}", 20 block.height, reveal.commitment 21 ) 22 })?; 23 let transaction = decrypt_blinded_transaction(&active_transaction.transaction, reveal)?; 24 if matches!(transaction, Transaction::Mine { .. }) { 25 bail!("block {} blinded reveal is a mine action", block.height); 26 } 27 if blinded_envelope_fee_for_transaction(&transaction) 28 != active_transaction.transaction.fee 29 { 30 bail!( 31 "block {} blinded reveal fee does not match envelope", 32 block.height 33 ); 34 } 35 revealed.push(RevealedBlindedTransaction { 36 height: block.height, 37 commitment: reveal.commitment.clone(), 38 included_by: active_transaction.included_by.clone(), 39 transaction, 40 }); 41 active.remove(&reveal.commitment); 42 } 43 active.retain(|_, active_transaction| { 44 block.height < active_transaction.transaction.expires_at_height 45 }); 46 for transaction in &block.blinded_transactions { 47 active.insert( 48 transaction.commitment.clone(), 49 ActiveBlindedTransaction { 50 transaction: transaction.clone(), 51 locked_outputs: Vec::new(), 52 included_height: block.height, 53 included_by: block.miner.clone(), 54 }, 55 ); 56 } 57 } 58 Ok(revealed) 59 }