use secp256k1::PublicKey;
use secp256k1::SecretKey;
use crate::crypto::SignatureHash;
use crate::transaction::Error;
use crate::transaction::SpendingCondition;
use crate::transaction::Transaction;
#[derive(Debug)]
pub struct TransactionSigner {
pub tx: Transaction,
pub hash: SignatureHash,
pub origin_signed: bool,
pub verify_oversign: bool,
pub verify_overlap: bool,
}
impl TransactionSigner {
pub fn new(tx: Transaction) -> Result<Self, Error> {
let hash = tx.initial_hash()?;
Ok(Self {
tx,
hash,
origin_signed: false,
verify_oversign: true,
verify_overlap: true,
})
}
pub fn new_sponser(
tx: &Transaction,
sponsor: Box<dyn SpendingCondition>,
) -> Result<Self, Error> {
if !tx.auth.is_sponsored() {
return Err(Error::BadSpendingConditionModification);
}
let mut tx = tx.clone();
tx.auth.set_sponsor(sponsor)?;
let hash = tx.verify_origin()?;
let mut signer = Self::new(tx)?;
signer.hash = hash;
signer.origin_signed = true;
signer.verify_oversign = true;
signer.verify_overlap = true;
Ok(signer)
}
pub fn sign_origin(&mut self, pk: SecretKey) -> Result<(), Error> {
if self.verify_overlap && self.origin_signed {
return Err(Error::OriginPostSponsorSign);
}
let origin = self.tx.auth.origin();
if self.verify_oversign && origin.signatures() >= origin.req_signatures() {
Err(Error::OriginOversign)
} else {
let next = self.tx.sign_next_origin(self.hash, pk)?;
self.hash = next;
Ok(())
}
}
pub fn sign_sponsor(&mut self, pk: SecretKey) -> Result<(), Error> {
let sponsor = self.tx.auth.sponsor()?;
if self.verify_oversign && sponsor.signatures() >= sponsor.req_signatures() {
Err(Error::SponsorOversign)
} else {
let next = self.tx.sign_next_sponsor(self.hash, pk)?;
self.origin_signed = true;
self.hash = next;
Ok(())
}
}
pub fn append_origin(&mut self, pk: PublicKey) -> Result<(), Error> {
if self.verify_overlap && self.origin_signed {
Err(Error::OriginPostSponsorAppend)
} else {
self.tx.append_next_origin(pk)
}
}
pub fn transaction(self) -> Transaction {
self.tx
}
}