From dc768c524268d1cfbd5acbf9effd259c0bea3bbc Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Sat, 19 Oct 2024 00:16:58 +0100 Subject: [PATCH 1/4] schnorr --- packages/engine/src/signature/constants.cairo | 5 ++++ packages/engine/src/signature/signature.cairo | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/packages/engine/src/signature/constants.cairo b/packages/engine/src/signature/constants.cairo index a543cfab..87afe8c7 100644 --- a/packages/engine/src/signature/constants.cairo +++ b/packages/engine/src/signature/constants.cairo @@ -44,3 +44,8 @@ pub const WITNESS_V0_PUB_KEY_HASH_LEN: usize = 22; pub const MAX_U128: u128 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; pub const MAX_U32: u32 = 0xFFFFFFFF; + +pub const SCHNORR_SIGNATURE_LEN: usize = 64; + +pub const PUB_KEY_BYTES_LEN: usize = 32; +pub const PUB_KEY_BYTES_LEN_COMPRESSED: usize = 33; \ No newline at end of file diff --git a/packages/engine/src/signature/signature.cairo b/packages/engine/src/signature/signature.cairo index 773ecf76..24c426cc 100644 --- a/packages/engine/src/signature/signature.cairo +++ b/packages/engine/src/signature/signature.cairo @@ -387,6 +387,35 @@ pub fn parse_pub_key(pk_bytes: @ByteArray) -> Result { } } +// ParsePubKey parses a public key for a koblitz curve from a bytestring into a +// Secp256k1Point, verifying that it is valid. It only supports public keys in +// the BIP-340 32-byte format. +pub fn parse_schnorr_pub_key(pub_key_str: @ByteArray) -> Result { + if pub_key_str.len() == 0 { + return Result::Err('nil pubkey byte string'); + } + if pub_key_str.len() != constants::PUB_KEY_BYTES_LEN { + return Result::Err('bad pubkey byte string size'); + } + + let mut key_compressed = ""; + key_compressed.append_byte(0x02); + key_compressed.append(pub_key_str); + + if key_compressed.len() != constants::PUB_KEY_BYTES_LEN_COMPRESSED { + return Result::Err('Invalid compressed public key'); + } + + let pub_key: u256 = u256_from_byte_array_with_offset(@key_compressed, 1,constants:: PUB_KEY_BYTES_LEN); + let parity: bool = key_compressed[0] == 0x03; + + Result::Ok( + Secp256Trait::::secp256_ec_get_point_from_x_syscall(pub_key, parity) + .unwrap_syscall() + .expect('Secp256k1Point: Invalid point.') + ) +} + // Parses a DER-encoded ECDSA signature byte array into a `Signature` struct. // // This function extracts the `r` and `s` values from a DER-encoded ECDSA signature (`sig_bytes`). From 80c0e94d15a779bf85f7d2d7381da7437fe0fbe2 Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Sat, 19 Oct 2024 16:23:51 +0100 Subject: [PATCH 2/4] taproot wip --- packages/engine/src/signature/signature.cairo | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/packages/engine/src/signature/signature.cairo b/packages/engine/src/signature/signature.cairo index 24c426cc..18845e22 100644 --- a/packages/engine/src/signature/signature.cairo +++ b/packages/engine/src/signature/signature.cairo @@ -549,6 +549,81 @@ pub fn parse_base_sig_and_pk< Result::Ok((pub_key, sig, hash_type)) } +pub struct TaprootSigVerifier { + pub_key: Secp256k1Point, + sig: Signature, + full_sig_bytes: @ByteArray, + pk_bytes: @ByteArray, + hash_type: u32, + tx_idx: u32, + annex: Option, +} + +pub trait TaprootSigVerifierTrait< + I, + O, + T, + +EngineTransactionInputTrait, + +EngineTransactionOutputTrait, + +EngineTransactionTrait +> { + fn new( + ref vm: Engine, + pk_bytes: @ByteArray, + full_sig_bytes: @ByteArray, + annex: Option + ) -> Result; + fn verify(ref self: TaprootSigVerifier, ref vm: Engine) -> bool; +} + +impl TaprootSigVerifierImpl< + I, + O, + T, + impl IEngineTransactionInput: EngineTransactionInputTrait, + impl IEngineTransactionOutput: EngineTransactionOutputTrait, + impl IEngineTransaction: EngineTransactionTrait< + T, I, O, IEngineTransactionInput, IEngineTransactionOutput + >, + +Drop, + +Drop, + +Drop +> of TaprootSigVerifierTrait { + fn new( + ref vm: Engine, + pk_bytes: @ByteArray, + full_sig_bytes: @ByteArray, + annex: Option + ) -> Result { + let (pub_key, sig, hash_type) = parse_taproot_sig_and_pk(pk_bytes, full_sig_bytes)?; + + Result::Ok(TaprootSigVerifier { + pub_key, + sig, + full_sig_bytes, + pk_bytes, + hash_type, + tx_idx: vm.tx_idx, + annex, + }) + } + + fn verify(ref self: TaprootSigVerifier, ref vm: Engine) -> bool { + // TODO: Implement the verification logic + // This is a placeholder implementation + false + } +} + +fn parse_taproot_sig_and_pk( + pk_bytes: @ByteArray, + raw_sig: @ByteArray +) -> Result<(Secp256k1Point, Signature, u32), felt252> { + // TODO: Implement the parsing logic + // This is a placeholder implementation + Result::Err('Not implemented') +} + // Removes the ECDSA signature from a given script. pub fn remove_signature(script: @ByteArray, sig_bytes: @ByteArray) -> @ByteArray { if script.len() == 0 || sig_bytes.len() == 0 { From da008337f990ac3190f6f20dc1d48006b7876f16 Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Sat, 19 Oct 2024 18:52:34 +0100 Subject: [PATCH 3/4] taproot::new --- packages/engine/src/signature/constants.cairo | 2 +- packages/engine/src/signature/signature.cairo | 64 ++++++++----------- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/packages/engine/src/signature/constants.cairo b/packages/engine/src/signature/constants.cairo index 87afe8c7..026648ee 100644 --- a/packages/engine/src/signature/constants.cairo +++ b/packages/engine/src/signature/constants.cairo @@ -48,4 +48,4 @@ pub const MAX_U32: u32 = 0xFFFFFFFF; pub const SCHNORR_SIGNATURE_LEN: usize = 64; pub const PUB_KEY_BYTES_LEN: usize = 32; -pub const PUB_KEY_BYTES_LEN_COMPRESSED: usize = 33; \ No newline at end of file +pub const PUB_KEY_BYTES_LEN_COMPRESSED: usize = 33; diff --git a/packages/engine/src/signature/signature.cairo b/packages/engine/src/signature/signature.cairo index 18845e22..1f3abc90 100644 --- a/packages/engine/src/signature/signature.cairo +++ b/packages/engine/src/signature/signature.cairo @@ -406,7 +406,9 @@ pub fn parse_schnorr_pub_key(pub_key_str: @ByteArray) -> Result, } pub trait TaprootSigVerifierTrait< @@ -568,10 +581,7 @@ pub trait TaprootSigVerifierTrait< +EngineTransactionTrait > { fn new( - ref vm: Engine, - pk_bytes: @ByteArray, - full_sig_bytes: @ByteArray, - annex: Option + ref vm: Engine, sig_bytes: @ByteArray, pk_bytes: @ByteArray ) -> Result; fn verify(ref self: TaprootSigVerifier, ref vm: Engine) -> bool; } @@ -590,38 +600,20 @@ impl TaprootSigVerifierImpl< +Drop > of TaprootSigVerifierTrait { fn new( - ref vm: Engine, - pk_bytes: @ByteArray, - full_sig_bytes: @ByteArray, - annex: Option + ref vm: Engine, sig_bytes: @ByteArray, pk_bytes: @ByteArray ) -> Result { - let (pub_key, sig, hash_type) = parse_taproot_sig_and_pk(pk_bytes, full_sig_bytes)?; - - Result::Ok(TaprootSigVerifier { - pub_key, - sig, - full_sig_bytes, - pk_bytes, - hash_type, - tx_idx: vm.tx_idx, - annex, - }) + let (pub_key, sig, hash_type) = parse_base_sig_and_pk(ref vm, pk_bytes, sig_bytes)?; + let sub_script = vm.sub_script(); + Result::Ok(TaprootSigVerifier { pub_key, sig, sig_bytes, pk_bytes, sub_script, hash_type }) } - fn verify(ref self: TaprootSigVerifier, ref vm: Engine) -> bool { - // TODO: Implement the verification logic - // This is a placeholder implementation - false - } -} + let sig_hashes = SigHashMidstateTrait::new(vm.transaction); + let sig_hash: u256 = sighash::calc_witness_signature_hash::< + I, O, T + >(@self.sub_script, @sig_hashes, self.hash_type, vm.transaction, vm.tx_idx, vm.amount); -fn parse_taproot_sig_and_pk( - pk_bytes: @ByteArray, - raw_sig: @ByteArray -) -> Result<(Secp256k1Point, Signature, u32), felt252> { - // TODO: Implement the parsing logic - // This is a placeholder implementation - Result::Err('Not implemented') + is_valid_signature(sig_hash, self.sig.r, self.sig.s, self.pub_key) + } } // Removes the ECDSA signature from a given script. From 5971bc7d1c34b41fb20b2a3e9cea826c8d4920ba Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Sat, 19 Oct 2024 19:08:49 +0100 Subject: [PATCH 4/4] taproot::new --- packages/engine/src/signature/signature.cairo | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/engine/src/signature/signature.cairo b/packages/engine/src/signature/signature.cairo index 1f3abc90..e4a12bbc 100644 --- a/packages/engine/src/signature/signature.cairo +++ b/packages/engine/src/signature/signature.cairo @@ -551,10 +551,6 @@ pub fn parse_base_sig_and_pk< Result::Ok((pub_key, sig, hash_type)) } -// TaprootSigVerifierImpl::new : use this as a reference from btcd -// https://github.com/btcsuite/btcd/blob/24eb815168f49dea84767817717a11bd7928eb23/txscript/sigvalidate.go#L313 -// TaprootSigVerifierImpl::verify : use this as a reference from btcd - //`TaprootSigVerifier` is used to verify Schnorr signatures encoded in the Taproot format. #[derive(Drop)] pub struct TaprootSigVerifier {