use bitcoin::{
blockdata::script::Script, blockdata::transaction::SigHashType,
util::bip143::SighashComponents, PublicKey,
};
use secp256k1::{self, Message, Secp256k1, SecretKey, Signature, Signing, Verification};
use std::borrow::ToOwned;
use crate::{Sha256dHash, TxInRef, UnspentTxOutValue};
#[derive(Debug, Clone, PartialEq)]
pub struct InputSignature(Vec<u8>);
impl InputSignature {
pub fn new(mut inner: Vec<u8>, sighash_type: SigHashType) -> InputSignature {
inner.push(sighash_type as u8);
InputSignature(inner)
}
pub fn from_bytes(bytes: Vec<u8>) -> Result<InputSignature, secp256k1::Error> {
InputSignatureRef::from_bytes(bytes.as_ref())?;
Ok(InputSignature(bytes))
}
pub fn content(&self) -> &[u8] {
self.0.split_last().unwrap().1
}
pub fn sighash_type(&self) -> SigHashType {
let byte = *self.0.last().unwrap();
SigHashType::from_u32(u32::from(byte))
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InputSignatureRef<'a>(&'a [u8]);
impl<'a> InputSignatureRef<'a> {
pub fn from_bytes(bytes: &'a [u8]) -> Result<InputSignatureRef<'a>, secp256k1::Error> {
let (_sighash_type, content) = bytes
.split_last()
.ok_or_else(|| secp256k1::Error::InvalidMessage)?;
Signature::from_der(content)?;
Ok(InputSignatureRef(bytes))
}
pub fn content(&self) -> &[u8] {
self.0.split_last().unwrap().1
}
pub fn sighash_type(&self) -> SigHashType {
let byte = *self.0.last().unwrap();
SigHashType::from_u32(u32::from(byte))
}
}
impl From<InputSignature> for Vec<u8> {
fn from(s: InputSignature) -> Self {
s.0
}
}
impl AsRef<[u8]> for InputSignature {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<'a> AsRef<[u8]> for InputSignatureRef<'a> {
fn as_ref(&self) -> &[u8] {
self.0
}
}
impl<'a> From<&'a InputSignature> for InputSignatureRef<'a> {
fn from(s: &'a InputSignature) -> InputSignatureRef {
InputSignatureRef(s.0.as_ref())
}
}
impl<'a> From<InputSignatureRef<'a>> for Vec<u8> {
fn from(s: InputSignatureRef<'a>) -> Vec<u8> {
s.0.to_owned()
}
}
impl<'a> From<InputSignatureRef<'a>> for InputSignature {
fn from(s: InputSignatureRef<'a>) -> InputSignature {
InputSignature(s.0.to_owned())
}
}
pub fn signature_hash<'a, 'b, V: Into<UnspentTxOutValue<'b>>>(
txin: TxInRef<'a>,
script: &Script,
value: V,
) -> Sha256dHash {
let value = value.into().balance(txin);
SighashComponents::new(txin.transaction)
.sighash_all(txin.as_ref(), script, value)
.as_hash()
}
pub fn sign_input<'a, 'b, C, V>(
context: &mut Secp256k1<C>,
txin: TxInRef<'a>,
script: &Script,
value: V,
secret_key: &SecretKey,
) -> Result<InputSignature, secp256k1::Error>
where
C: Signing,
V: Into<UnspentTxOutValue<'b>>,
{
let sighash = signature_hash(txin, script, value);
let msg = Message::from_slice(&sighash[..])?;
let signature = context.sign(&msg, secret_key).serialize_der().to_vec();
Ok(InputSignature::new(signature, SigHashType::All))
}
pub fn verify_input_signature<'a, 'b, C, V>(
context: &Secp256k1<C>,
txin: TxInRef<'a>,
script: &Script,
value: V,
public_key: &PublicKey,
signature: &[u8],
) -> Result<(), secp256k1::Error>
where
C: Verification,
V: Into<UnspentTxOutValue<'b>>,
{
let sighash = signature_hash(txin, script, value);
let msg = Message::from_slice(&sighash[..])?;
let sign = Signature::from_der(signature)?;
context.verify(&msg, &sign, &public_key.key)
}
#[test]
fn test_input_signature_ref_incorrect() {
let bytes = b"abacaba";
InputSignatureRef::from_bytes(bytes).expect_err("Signature should be incorrect");
InputSignature::from_bytes(bytes.to_vec()).expect_err("Signature should be incorrect");
}
#[test]
fn test_input_signature_ref_correct() {
let bytes = ::hex::decode(
"304402201538279618a4626653775069b43d4315c7d2ff30008d339d0ed31ff41e628e71022028f3182fc39df\
28201ca4d7d489aece7bc5bc6bfe05b09b6a9d3b70bf5f3743101",
)
.unwrap();
InputSignatureRef::from_bytes(&bytes).expect("Signature should be correct");
InputSignature::from_bytes(bytes).expect("Signature should be correct");
}