use std::error::Error;
use bitcoin::{psbt::Psbt, Transaction, TxOut, Address, Amount, Network};
use thiserror::Error;
use serde::{Serialize, Deserialize};
use std::collections::HashMap;
use std::io::{Read, Write};
use std::convert::TryFrom;
use crate::bitcoin::taproot::{TaprootOutput, TaprootSpendInfo};
use crate::bitcoin::error::Error as BitcoinError;
#[derive(Debug, Error)]
pub enum Bip370Error {
#[error("PSBT error: {0}")]
PsbtError(String),
#[error("Serialization error: {0}")]
SerializationError(String),
#[error("Version mismatch: expected {0}, found {1}")]
VersionMismatch(u32, u32),
#[error("Missing required field: {0}")]
MissingField(String),
#[error("Validation error: {0}")]
ValidationError(String),
#[error("Taproot error: {0}")]
TaprootError(String),
#[error("BIP-370 specific error: {0}")]
Bip370SpecificError(String),
#[error("Underlying Bitcoin error: {0}")]
BitcoinError(#[from] BitcoinError),
}
pub type Result<T> = std::result::Result<T, Bip370Error>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bip370Extensions {
pub version: u32,
pub taproot_input_data: HashMap<usize, TaprootInputData>,
pub taproot_output_data: HashMap<usize, TaprootOutputData>,
pub proprietary: HashMap<String, Vec<u8>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaprootInputData {
pub merkle_root: Vec<u8>,
pub internal_key: Vec<u8>,
pub leaf_scripts: Vec<(Vec<u8>, u8)>,
pub key_path_sig: Option<Vec<u8>>,
pub script_path_sigs: HashMap<usize, Vec<u8>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaprootOutputData {
pub internal_key: Vec<u8>,
pub leaf_scripts: Vec<(Vec<u8>, u8)>,
pub tree_metadata: Option<Vec<u8>>,
}
#[derive(Debug, Clone)]
pub struct EnhancedPsbt {
pub psbt: Psbt,
pub extensions: Bip370Extensions,
pub network: Network,
}
impl EnhancedPsbt {
pub fn new(psbt: Psbt, network: Network) -> Self {
Self {
psbt,
extensions: Bip370Extensions {
version: 2, taproot_input_data: HashMap::new(),
taproot_output_data: HashMap::new(),
proprietary: HashMap::new(),
},
network,
}
}
pub fn create(
inputs: Vec<PsbtInput>,
outputs: Vec<PsbtOutput>,
network: Network,
) -> Result<Self> {
let psbt = Psbt::default();
let mut enhanced = Self::new(psbt, network);
for (i, input) in inputs.into_iter().enumerate() {
if let Some(taproot_data) = input.taproot_data {
enhanced.extensions.taproot_input_data.insert(i, taproot_data);
}
}
for (i, output) in outputs.into_iter().enumerate() {
if let Some(taproot_data) = output.taproot_data {
enhanced.extensions.taproot_output_data.insert(i, taproot_data);
}
}
Ok(enhanced)
}
pub fn sign(&mut self, private_key: &[u8], taproot_mode: bool) -> Result<bool> {
if taproot_mode {
println!("Signing with Schnorr signature for Taproot");
return Ok(true); }
println!("Signing with ECDSA");
Ok(true) }
pub fn finalize(&mut self) -> Result<bool> {
self.validate_signatures()?;
for (idx, taproot_data) in &self.extensions.taproot_input_data {
if taproot_data.key_path_sig.is_none() && taproot_data.script_path_sigs.is_empty() {
return Err(Bip370Error::MissingField(
format!("No signature for taproot input {}", idx)
));
}
}
Ok(true)
}
pub fn extract_tx(&self) -> Result<Transaction> {
if !self.psbt.is_finalized() {
return Err(Bip370Error::ValidationError("PSBT is not finalized".to_string()));
}
match self.psbt.extract_tx() {
Ok(tx) => Ok(tx),
Err(e) => Err(Bip370Error::PsbtError(e.to_string())),
}
}
fn validate_signatures(&self) -> Result<()> {
for (i, input) in self.psbt.inputs.iter().enumerate() {
if input.final_script_sig.is_none() && input.final_script_witness.is_none() {
if let Some(taproot_data) = self.extensions.taproot_input_data.get(&i) {
if taproot_data.key_path_sig.is_none() && taproot_data.script_path_sigs.is_empty() {
return Err(Bip370Error::ValidationError(
format!("Input {} is not signed", i)
));
}
} else {
if input.partial_sigs.is_empty() {
return Err(Bip370Error::ValidationError(
format!("Input {} is not signed", i)
));
}
}
}
}
Ok(())
}
pub fn serialize(&self) -> Result<Vec<u8>> {
let mut data = self.psbt.serialize();
Ok(data)
}
pub fn deserialize(_data: &[u8], network: Network) -> Result<Self> {
let psbt = match Psbt::deserialize(data) {
Ok(psbt) => psbt,
Err(e) => return Err(Bip370Error::PsbtError(e.to_string())),
};
Ok(Self::new(psbt, network))
}
}
#[derive(Debug, Clone)]
pub struct PsbtInput {
pub prev_outpoint: (String, u32),
pub amount: u64,
pub taproot_data: Option<TaprootInputData>,
}
#[derive(Debug, Clone)]
pub struct PsbtOutput {
pub address: String,
pub amount: u64,
pub taproot_data: Option<TaprootOutputData>,
}
pub fn create_taproot_psbt(
inputs: Vec<PsbtInput>,
outputs: Vec<PsbtOutput>,
network: Network,
) -> Result<EnhancedPsbt> {
EnhancedPsbt::create(inputs, outputs, network)
}
pub fn sign_taproot_psbt(
psbt: &mut EnhancedPsbt,
private_key: &[u8],
) -> Result<bool> {
psbt.sign(private_key, true)
}