use std::collections::BTreeSet;
use masp_primitives::merkle_tree::CommitmentTree;
use masp_primitives::sapling::Node;
use masp_primitives::transaction::Transaction;
use crate::storage_key::{
is_masp_transfer_key, masp_commitment_tree_key, masp_nullifier_key,
};
use crate::{Error, Key, Result, StorageRead, StorageWrite};
fn reveal_nullifiers(
ctx: &mut impl StorageWrite,
transaction: &Transaction,
) -> Result<()> {
for description in transaction
.sapling_bundle()
.map_or(&vec![], |description| &description.shielded_spends)
{
ctx.write(&masp_nullifier_key(&description.nullifier), ())?;
}
Ok(())
}
pub fn update_note_commitment_tree(
ctx: &mut (impl StorageRead + StorageWrite),
transaction: &Transaction,
) -> Result<()> {
if let Some(bundle) = transaction.sapling_bundle() {
if !bundle.shielded_outputs.is_empty() {
let tree_key = masp_commitment_tree_key();
let mut commitment_tree: CommitmentTree<Node> =
ctx.read(&tree_key)?.ok_or(Error::SimpleMessage(
"Missing note commitment tree in storage",
))?;
for description in &bundle.shielded_outputs {
commitment_tree
.append(Node::from_scalar(description.cmu))
.map_err(|_| {
Error::SimpleMessage("Note commitment tree is full")
})?;
}
ctx.write(&tree_key, commitment_tree)?;
}
}
Ok(())
}
pub fn handle_masp_tx(
ctx: &mut (impl StorageRead + StorageWrite),
shielded: &Transaction,
) -> Result<()> {
reveal_nullifiers(ctx, shielded)?;
Ok(())
}
pub fn is_masp_transfer(changed_keys: &BTreeSet<Key>) -> bool {
changed_keys.iter().any(is_masp_transfer_key)
}