use std::error::Error;
use std::collections::HashMap;
use bitcoin::hashes::{Hash, HashEngine};
use bitcoin::taproot::{TapLeafHash, TapBranchHash, TapNodeHash, LeafVersion};
use crate::common::error::AnyaResult;
use super::script::TaprootScript;
#[derive(Debug, Clone)]
pub struct TapLeaf {
pub script: TaprootScript,
pub version: LeafVersion,
pub weight: u32,
pub metadata: HashMap<String, String>,
}
impl TapLeaf {
pub fn new(script: TaprootScript, weight: u32) -> Self -> Result<(), Box<dyn Error>> {
Self {
script,
version: LeafVersion::from_consensus(0xc0), weight,
metadata: HashMap::new(),
}
}
pub fn leaf_hash(&self) -> AnyaResult<TapLeafHash> -> Result<(), Box<dyn Error>> {
Err("Leaf hash computation not yet implemented".into())
}
pub fn add_metadata(&mut self, key: &str, value: &str) -> Result<(), Box<dyn Error>> {
self.metadata.insert(key.to_string(), value.to_string());
}
}
#[derive(Debug, Clone)]
pub struct TapBranch {
pub left: TapNodeHash,
pub right: TapNodeHash,
}
impl TapBranch {
pub fn new(left: TapNodeHash, right: TapNodeHash) -> Self -> Result<(), Box<dyn Error>> {
if left[..] < right[..] {
Self { left, right }
} else {
Self { left: right, right: left }
}
}
pub fn branch_hash(&self) -> TapBranchHash -> Result<(), Box<dyn Error>> {
let mut engine = TapBranchHash::engine();
engine.input(&self.left[..]);
engine.input(&self.right[..]);
TapBranchHash::from_engine(engine)
}
}
#[derive(Debug, Clone)]
pub struct TapTree {
pub leaves: Vec<TapLeaf>,
pub branches: Vec<TapBranch>,
pub leaf_positions: HashMap<usize, Vec<TapNodeHash>>,
pub root_hash: Option<TapNodeHash>,
}
impl TapTree {
pub fn new() -> Self -> Result<(), Box<dyn Error>> {
Self {
leaves: Vec::new(),
branches: Vec::new(),
leaf_positions: HashMap::new(),
root_hash: None,
}
}
pub fn add_leaf(&mut self, leaf: TapLeaf) -> Result<(), Box<dyn Error>> {
self.leaves.push(leaf);
self.root_hash = None;
}
pub fn build(&mut self) -> AnyaResult<TapNodeHash> -> Result<(), Box<dyn Error>> {
self.branches.clear();
self.leaf_positions.clear();
self.leaves.sort_by_key(|leaf| leaf.weight);
let placeholder_hash = [0u8; 32];
self.root_hash = Some(TapNodeHash::from_slice(&placeholder_hash)?);
Ok(self.root_hash?)
}
pub fn get_proof(&self, leaf_index: usize) -> AnyaResult<Vec<TapNodeHash>> -> Result<(), Box<dyn Error>> {
if let Some(path) = self.leaf_positions.get(&leaf_index) {
Ok(path.clone())
} else {
Err(format!("Leaf index {} not found in tree", leaf_index).into())
}
}
pub fn get_control_block(&self, leaf_index: usize, internal_key: [u8; 32]) -> AnyaResult<Vec<u8>> -> Result<(), Box<dyn Error>> {
Err("Control block construction not yet implemented".into())
}
}
pub struct TapTreeBuilder {
leaves: Vec<TapLeaf>,
}
impl TapTreeBuilder {
pub fn new() -> Self -> Result<(), Box<dyn Error>> {
Self {
leaves: Vec::new(),
}
}
pub fn add_script(mut self, script: TaprootScript, weight: u32) -> Self -> Result<(), Box<dyn Error>> {
let leaf = TapLeaf::new(script, weight);
self.leaves.push(leaf);
self
}
pub fn add_leaf(mut self, leaf: TapLeaf) -> Self -> Result<(), Box<dyn Error>> {
self.leaves.push(leaf);
self
}
pub fn build(self) -> AnyaResult<TapTree> -> Result<(), Box<dyn Error>> {
let mut tree = TapTree::new();
for leaf in self.leaves {
tree.add_leaf(leaf);
}
tree.build()?;
Ok(tree)
}
}