Skip to content

Commit

Permalink
Feat:taproot new (#274)
Browse files Browse the repository at this point in the history
<!-- enter the gh issue after hash -->

- [ ] resolves #
- [ ] follows contribution
[guide](https://github.com/keep-starknet-strange/shinigami/blob/main/CONTRIBUTING.md)
- [ ] code change includes tests

<!-- PR description below -->

Adds features from this pr due to deleted branch :
#271

---------

Co-authored-by: Supreme2580 <victoromorogbe69@gmail.com>
  • Loading branch information
b-j-roberts and supreme2580 authored Oct 28, 2024
1 parent 71f483a commit 1a55189
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 9 deletions.
4 changes: 3 additions & 1 deletion packages/engine/src/opcodes/crypto.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ pub fn opcode_checksig<
}

// TODO: Errors or false?
let mut verifier = TaprootSigVerifierTrait::<T>::new_base(@full_sig_bytes, @pk_bytes)?;
let mut verifier = TaprootSigVerifierTrait::<
T
>::new_base(@full_sig_bytes, @pk_bytes, ref engine)?;
is_valid = TaprootSigVerifierTrait::<T>::verify(ref verifier);
}

Expand Down
68 changes: 60 additions & 8 deletions packages/engine/src/signature/signature.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,7 @@ pub fn parse_pub_key(pk_bytes: @ByteArray) -> Result<Secp256k1Point, felt252> {

pub fn parse_schnorr_pub_key(pk_bytes: @ByteArray) -> Result<Secp256k1Point, felt252> {
if pk_bytes.len() == 0 || pk_bytes.len() != 32 {
// TODO
panic!("invalid schnorr pubkey length");
return Result::Err('Invalid schnorr pubkey length');
}

let mut key_compressed: ByteArray = "\02";
Expand Down Expand Up @@ -458,6 +457,28 @@ pub fn parse_signature(sig_bytes: @ByteArray) -> Result<Signature, felt252> {
return Result::Ok(Signature { r: r_sig, s: s_sig, y_parity: false, });
}

pub fn schnorr_parse_signature(sig_bytes: @ByteArray) -> Result<(Signature, u32), felt252> {
let sig_bytes_len = sig_bytes.len();
let mut hash_type: u32 = 0;
if sig_bytes_len == SCHNORR_SIGNATURE_LEN {
hash_type = constants::SIG_HASH_DEFAULT;
} else if sig_bytes_len == SCHNORR_SIGNATURE_LEN + 1 && sig_bytes[64] != 0 {
hash_type = sig_bytes[64].into();
} else {
return Result::Err('Invalid taproot signature len');
}
Result::Ok(
(
Signature {
r: u256_from_byte_array_with_offset(sig_bytes, 0, 32),
s: u256_from_byte_array_with_offset(sig_bytes, 32, 32),
y_parity: false, // Schnorr signatures don't use y_parity
},
hash_type
)
)
}

// Parses the public key and signature byte arrays based on consensus rules.
// Returning a tuple containing the parsed public key, signature, and hash type.
pub fn parse_base_sig_and_pk<
Expand Down Expand Up @@ -579,14 +600,19 @@ pub struct TaprootSigVerifier {
}

pub trait TaprootSigVerifierTrait<T> {
fn empty() -> TaprootSigVerifier;
fn new(
sig_bytes: @ByteArray, pk_bytes: @ByteArray, annex: @ByteArray
) -> Result<TaprootSigVerifier, felt252>;
fn new_base(sig_bytes: @ByteArray, pk_bytes: @ByteArray) -> Result<TaprootSigVerifier, felt252>;
fn new_base(
sig_bytes: @ByteArray, pk_bytes: @ByteArray, ref engine: Engine<T>
) -> Result<TaprootSigVerifier, felt252>;
fn verify(ref self: TaprootSigVerifier) -> bool;
fn verify_base(ref self: TaprootSigVerifier) -> bool;
}

pub const SCHNORR_SIGNATURE_LEN: usize = 64;

pub impl TaprootSigVerifierImpl<
T,
+Drop<T>,
Expand All @@ -600,18 +626,44 @@ pub impl TaprootSigVerifierImpl<
T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait
>
> of TaprootSigVerifierTrait<T> {
fn empty() -> TaprootSigVerifier {
TaprootSigVerifier {
pub_key: Secp256Trait::<Secp256k1Point>::get_generator_point(),
sig: Signature { r: 0, s: 0, y_parity: false },
sig_bytes: @"",
pk_bytes: @"",
hash_type: 0,
annex: @""
}
}

fn new(
sig_bytes: @ByteArray, pk_bytes: @ByteArray, annex: @ByteArray
) -> Result<TaprootSigVerifier, felt252> {
// TODO
return Result::Err('TaprootSig not implemented');
let pub_key = parse_schnorr_pub_key(pk_bytes)?;
let (sig, hash_type) = schnorr_parse_signature(sig_bytes)?;

Result::Ok(
TaprootSigVerifier {
pub_key, sig, sig_bytes: sig_bytes, pk_bytes: pk_bytes, hash_type, annex,
}
)
}

fn new_base(
sig_bytes: @ByteArray, pk_bytes: @ByteArray
sig_bytes: @ByteArray, pk_bytes: @ByteArray, ref engine: Engine<T>
) -> Result<TaprootSigVerifier, felt252> {
// TODO
return Result::Err('TaprootSig not implemented');
let pk_bytes_len = pk_bytes.len();
if pk_bytes_len == 0 {
return Result::Err('Taproot empty public key');
} else if pk_bytes_len == 32 {
return Self::new(sig_bytes, pk_bytes, engine.taproot_context.annex);
} else {
if engine.has_flag(ScriptFlags::ScriptVerifyDiscourageUpgradeablePubkeyType) {
return Result::Err('Unknown pub key type');
}
return Result::Ok(Self::empty());
}
}

fn verify(ref self: TaprootSigVerifier) -> bool {
Expand Down

0 comments on commit 1a55189

Please sign in to comment.