use {
super::*,
base64::{Engine, engine::general_purpose},
};
#[derive(Debug, Parser)]
#[clap(
group(
ArgGroup::new("input")
.required(true)
.args(&["text", "file"])),
group(
ArgGroup::new("signature")
.required(true)
.args(&["transaction", "witness"]))
)]
pub(crate) struct Verify {
#[arg(long, help = "Verify signature made by <ADDRESS>.")]
address: Address<NetworkUnchecked>,
#[arg(long, help = "Verify signature over <TEXT>.")]
text: Option<String>,
#[arg(long, help = "Verify signature over contents of <FILE>.")]
file: Option<PathBuf>,
#[arg(long, help = "Verify base64-encoded <WITNESS>.")]
witness: Option<String>,
#[arg(long, help = "Verify base64-encoded <TRANSACTION>.")]
transaction: Option<String>,
}
impl Verify {
pub(crate) fn run(self) -> SubcommandResult {
let message = if let Some(text) = &self.text {
text.as_bytes()
} else if let Some(file) = &self.file {
&fs::read(file)?
} else {
unreachable!()
};
if let Some(witness) = self.witness {
let mut cursor = bitcoin::io::Cursor::new(general_purpose::STANDARD.decode(witness)?);
let witness = Witness::consensus_decode_from_finite_reader(&mut cursor)?;
bip322::verify_simple(&self.address.assume_checked(), message, witness)?;
} else if let Some(transaction) = self.transaction {
let mut cursor = bitcoin::io::Cursor::new(general_purpose::STANDARD.decode(transaction)?);
let transaction = Transaction::consensus_decode_from_finite_reader(&mut cursor)?;
bip322::verify_full(&self.address.assume_checked(), message, transaction)?;
} else {
unreachable!();
}
Ok(None)
}
}