use std::collections::BTreeMap;
use zcash_client_backend::data_api::locking::LockOwner;
use zcash_client_backend::wallet::OutputRef;
use zcash_protocol::consensus::BlockHeight;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct OutputLock {
owner: LockOwner,
expiry_height: BlockHeight,
}
#[derive(Debug, Clone, Default)]
pub struct OutputLocks(BTreeMap<OutputRef, OutputLock>);
impl OutputLocks {
pub fn acquire(
&mut self,
outputs: &[OutputRef],
owner: LockOwner,
expiry_height: BlockHeight,
chain_tip: BlockHeight,
) -> Result<usize, OutputRef> {
if let Some(held) = outputs.iter().find(|output| {
self.0
.get(output)
.is_some_and(|lock| lock.owner != owner && lock.expiry_height > chain_tip)
}) {
return Err(*held);
}
for output in outputs {
self.0.insert(
*output,
OutputLock {
owner,
expiry_height,
},
);
}
Ok(outputs.len())
}
pub fn release(&mut self, output: &OutputRef, owner: LockOwner) -> bool {
if self.0.get(output).is_some_and(|lock| lock.owner == owner) {
self.0.remove(output);
return true;
}
false
}
pub fn discard(&mut self, output: &OutputRef) -> bool {
self.0.remove(output).is_some()
}
pub fn iter(&self) -> impl Iterator<Item = (OutputRef, BlockHeight)> + '_ {
self.0
.iter()
.map(|(output, lock)| (*output, lock.expiry_height))
}
}