Skip to content

Commit

Permalink
add winternitz and preimagereveal
Browse files Browse the repository at this point in the history
  • Loading branch information
atacann committed Feb 7, 2025
1 parent 8eefcf3 commit 61e9b80
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 45 deletions.
124 changes: 85 additions & 39 deletions core/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ use crate::builder::script::{
use crate::builder::transaction::input::SpentTxIn;
use crate::builder::transaction::TxHandler;
use crate::errors::BridgeError;
use crate::errors::BridgeError::NonOwnedKeyPath;
use crate::errors::BridgeError::NotOwnKeyPath;
use crate::operator::PublicHash;
use crate::rpc::clementine::tagged_signature::SignatureId;
use crate::rpc::clementine::TaggedSignature;
use crate::utils::{self, SECP};
use bitcoin::hashes::hash160;
use bitcoin::secp256k1::PublicKey;
use bitcoin::sighash::{self, SighashCache};
use bitcoin::{hashes::Hash, secp256k1::{schnorr, Keypair, Message, SecretKey, XOnlyPublicKey}, Address, ScriptBuf, TapSighash, TapTweakHash};
use bitcoin::{TapNodeHash, TapSighashType, TxOut, Witness};
use bitcoin::taproot::{LeafVersion, TaprootSpendInfo};
use bitcoin::{
hashes::Hash,
secp256k1::{schnorr, Keypair, Message, SecretKey, XOnlyPublicKey},
Address, ScriptBuf, TapSighash, TapTweakHash,
};
use bitcoin::{TapNodeHash, TapSighashType, TxOut, Witness};
use bitvm::signatures::winternitz::{
self, BinarysearchVerifier, StraightforwardConverter, Winternitz,
};
Expand Down Expand Up @@ -302,14 +306,18 @@ impl Actor {
) -> Option<schnorr::Signature> {
signatures
.iter()
.find(|sig| sig.signature_id.map(|id| id == signature_id).unwrap_or(false))
.find(|sig| {
sig.signature_id
.map(|id| id == signature_id)
.unwrap_or(false)
})
.and_then(|sig| schnorr::Signature::from_slice(sig.signature.as_ref()).ok())
}

fn add_script_path_to_witness(
witness: &mut Witness,
script: &ScriptBuf,
spend_info: &TaprootSpendInfo
spend_info: &TaprootSpendInfo,
) -> Result<(), BridgeError> {
let spend_control_block = spend_info
.control_block(&(script.clone(), LeafVersion::TapScript))
Expand All @@ -323,7 +331,7 @@ impl Actor {
&self,
txhandler: &mut TxHandler,
signatures: &Vec<TaggedSignature>,
data: &[u8],
data: &Vec<u8>,
) -> Result<(), BridgeError> {
let txhandlerclone = txhandler.clone();
let signer = |idx: usize, spt: &SpentTxIn| -> Result<Option<Witness>, BridgeError> {
Expand All @@ -342,23 +350,43 @@ impl Actor {
let mut witness = Witness::default();

if let Some(script) = script.as_any().downcast_ref::<OtherSpendable>() {
return Ok(None)
return Ok(None);
} else if let Some(script) = script.as_any().downcast_ref::<DepositScript>() {
return Ok(None)
} else if let Some(script) = script.as_any().downcast_ref::<PreimageRevealScript>() {
return Ok(None)
return Ok(None);
} else if let Some(script) =
script.as_any().downcast_ref::<PreimageRevealScript>()
{
if (script.0 != self.xonly_public_key) {
return Err(BridgeError::NotOwnedScriptPath);
}
witness = script.generate_script_inputs(
data,
&self.sign_taproot_script_spend_tx(&txhandlerclone, idx, script_idx)?,
);
} else if let Some(script) = script.as_any().downcast_ref::<TimelockScript>() {
return Ok(None)
} else if let Some(script) = script.as_any().downcast_ref::<WinternitzCommit>() {
return Ok(None)
return Ok(None);
} else if let Some(script) = script.as_any().downcast_ref::<WinternitzCommit>()
{
if (script.2 != self.xonly_public_key) {
return Err(BridgeError::NotOwnedScriptPath);
}
witness = script.generate_script_inputs(
data,
&self.winternitz_secret_key
.ok_or(BridgeError::NoWinternitzSecretKey)?.as_ref().to_vec(),
&self.sign_taproot_script_spend_tx(&txhandlerclone, idx, script_idx)?,
);
} else if let Some(script) = script.as_any().downcast_ref::<CheckSig>() {
return Ok(None)
}
else {
return Err(BridgeError::Error("Not handled script type".to_string()))
return Ok(None);
} else {
return Err(BridgeError::Error("Not handled script type".to_string()));
}
Self::add_script_path_to_witness(&mut witness, &script.to_script_buf(), &spendinfo)?;
return Ok(Some(witness))
Self::add_script_path_to_witness(
&mut witness,
&script.to_script_buf(),
&spendinfo,
)?;
return Ok(Some(witness));
}
SpendPath::KeySpend => {
let xonly_public_key = spendinfo.internal_key();
Expand All @@ -373,7 +401,7 @@ impl Actor {
};
return Ok(Some(Witness::from_slice(&[&sig.serialize()])));
}
Err(NonOwnedKeyPath)
Err(NotOwnKeyPath)
}
SpendPath::Unknown => Err(BridgeError::SpendPathNotSpecified),
}
Expand Down Expand Up @@ -405,60 +433,78 @@ impl Actor {
let mut witness = Witness::default();

if let Some(script) = script.as_any().downcast_ref::<OtherSpendable>() {
return Ok(None)
return Ok(None);
} else if let Some(script) = script.as_any().downcast_ref::<DepositScript>() {
match sig {
None => {
if script.0 == self.xonly_public_key {
witness = script.generate_script_inputs(
&self.sign_taproot_script_spend_tx(&txhandlerclone, idx, script_idx)?,
&self.sign_taproot_script_spend_tx(
&txhandlerclone,
idx,
script_idx,
)?,
)
} else {
return Err(BridgeError::SignatureNotFound)
return Err(BridgeError::SignatureNotFound);
}
}
Some(sig) => witness = script.generate_script_inputs(&sig),
}
} else if let Some(script) = script.as_any().downcast_ref::<PreimageRevealScript>() {
return Ok(None)
} else if let Some(script) =
script.as_any().downcast_ref::<PreimageRevealScript>()
{
return Ok(None);
} else if let Some(script) = script.as_any().downcast_ref::<TimelockScript>() {
if let Some(xonly_key) = script.0 {
match sig {
None => {
if xonly_key == self.xonly_public_key {
witness = script.generate_script_inputs(
&Some(self.sign_taproot_script_spend_tx(&txhandlerclone, idx, script_idx)?),
)
witness = script.generate_script_inputs(&Some(
self.sign_taproot_script_spend_tx(
&txhandlerclone,
idx,
script_idx,
)?,
))
} else {
return Err(BridgeError::SignatureNotFound)
return Err(BridgeError::SignatureNotFound);
}
}
Some(sig) => witness = script.generate_script_inputs(&Some(sig)),
}
} else {
witness = Witness::new()
}
} else if let Some(script) = script.as_any().downcast_ref::<WinternitzCommit>() {
return Ok(None)
} else if let Some(script) = script.as_any().downcast_ref::<WinternitzCommit>()
{
return Ok(None);
} else if let Some(script) = script.as_any().downcast_ref::<CheckSig>() {
match sig {
None => {
if script.0 == self.xonly_public_key {
witness = script.generate_script_inputs(
&self.sign_taproot_script_spend_tx(&txhandlerclone, idx, script_idx)?,
&self.sign_taproot_script_spend_tx(
&txhandlerclone,
idx,
script_idx,
)?,
)
} else {
return Err(BridgeError::SignatureNotFound)
return Err(BridgeError::SignatureNotFound);
}
}
Some(sig) => witness = script.generate_script_inputs(&sig),
}
} else {
return Err(BridgeError::Error("Not handled script type".to_string()));
}
else {
return Err(BridgeError::Error("Not handled script type".to_string()))
}
Self::add_script_path_to_witness(&mut witness, &script.to_script_buf(), &spendinfo)?;
return Ok(Some(witness))
Self::add_script_path_to_witness(
&mut witness,
&script.to_script_buf(),
&spendinfo,
)?;
return Ok(Some(witness));
}
SpendPath::KeySpend => {
let xonly_public_key = spendinfo.internal_key();
Expand All @@ -473,7 +519,7 @@ impl Actor {
};
return Ok(Some(Witness::from_slice(&[&sig.serialize()])));
}
Err(NonOwnedKeyPath)
Err(NotOwnKeyPath)
}
SpendPath::Unknown => Err(BridgeError::SpendPathNotSpecified),
}
Expand Down
14 changes: 10 additions & 4 deletions core/src/builder/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl CheckSig {

/// Struct for scripts that commit to a message using Winternitz keys
#[derive(Clone)]
pub struct WinternitzCommit(PublicKey, Parameters, XOnlyPublicKey);
pub struct WinternitzCommit(PublicKey, Parameters, pub(crate) XOnlyPublicKey);
impl SpendableScript for WinternitzCommit {
fn as_any(&self) -> &dyn Any {
self
Expand Down Expand Up @@ -193,7 +193,7 @@ impl TimelockScript {
}

/// Struct for scripts that reveal a preimage and verify it against a hash.
pub struct PreimageRevealScript(XOnlyPublicKey, [u8; 20]);
pub struct PreimageRevealScript(pub(crate) XOnlyPublicKey, [u8; 20]);

impl SpendableScript for PreimageRevealScript {
fn as_any(&self) -> &dyn Any {
Expand All @@ -212,8 +212,14 @@ impl SpendableScript for PreimageRevealScript {
}

impl PreimageRevealScript {
pub fn generate_script_inputs(&self, preimage: &[u8], signature: &schnorr::Signature) -> Witness {
Witness::from_slice(&[preimage, &signature.serialize()])
pub fn generate_script_inputs(
&self,
preimage: impl AsRef<[u8]>,
signature: &schnorr::Signature,
) -> Witness {
let mut witness = Witness::from_slice(&[preimage]);
witness.push(signature.serialize());
witness
}

pub fn new(xonly_pk: XOnlyPublicKey, hash: [u8; 20]) -> Self {
Expand Down
1 change: 0 additions & 1 deletion core/src/builder/transaction/txhandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ impl TxHandler<Unsigned> {
test_closure();
self.txins[idx].set_witness(witness);
}

}
Ok(())
}
Expand Down
4 changes: 3 additions & 1 deletion core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ pub enum BridgeError {
#[error("Spend Path in SpentTxIn in TxHandler not specified")]
SpendPathNotSpecified,
#[error("Actor does not own the key needed in P2TR keypath")]
NonOwnedKeyPath,
NotOwnKeyPath,
#[error("public key of Checksig in script is not owned by Actor")]
NotOwnedScriptPath,
#[error("Couldn't find needed signature from database")]
SignatureNotFound,

Expand Down

0 comments on commit 61e9b80

Please sign in to comment.