From 6ebcc97098aec219c943d7bee7fefc747ccc8535 Mon Sep 17 00:00:00 2001 From: Brice Dobry <232827048+brice-stacks@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:12:53 -0500 Subject: [PATCH 1/4] fix: do not double hash in `secp256r1-verify` This is a consensus breaking change and will need to go out in a hard-fork with a new version of Clarity (Clarity5). In the existing implementation, the code was incorrectly hashing the passed in `message-hash`. Unfortunately, the test code was also double-hashing on the signing side as well, so this was not caught. The bug was discovered by @eric-stacks when attempting to generate signatures externally (e.g. with WebAuthn) and verify them in Clarity code. --- clarity/src/vm/docs/mod.rs | 2 +- clarity/src/vm/functions/crypto.rs | 13 +++- clarity/src/vm/version.rs | 9 +++ stacks-common/src/util/secp256r1.rs | 111 +++++++++++++++++++++++++++- 4 files changed, 126 insertions(+), 9 deletions(-) diff --git a/clarity/src/vm/docs/mod.rs b/clarity/src/vm/docs/mod.rs index 61db5ee1bc..dfcacf88fb 100644 --- a/clarity/src/vm/docs/mod.rs +++ b/clarity/src/vm/docs/mod.rs @@ -1410,7 +1410,7 @@ const SECP256R1VERIFY_API: SpecialAPI = SpecialAPI { description: "The `secp256r1-verify` function verifies that the provided signature of the message-hash was signed with the private key that generated the public key. `message-hash` is typically the `sha256` of a message and `signature` is the raw 64-byte signature. -High-S signatures are allowed. +High-S signatures are allowed. In Clarity 4, the `message-hash` is SHA256 hashed again internally before verification (i.e. double SHA256). Note that this is NOT the Bitcoin (or default Stacks) signature scheme, secp256k1, but rather the NIST P-256 curve (also known as secp256r1).", example: "(secp256r1-verify 0xc3abef6a775793dfbc8e0719e7a1de1fc2f90d37a7912b1ce8e300a5a03b06a8 diff --git a/clarity/src/vm/functions/crypto.rs b/clarity/src/vm/functions/crypto.rs index 7af6ddd13e..4e6bd05f2e 100644 --- a/clarity/src/vm/functions/crypto.rs +++ b/clarity/src/vm/functions/crypto.rs @@ -20,7 +20,7 @@ use stacks_common::address::{ use stacks_common::types::chainstate::StacksAddress; use stacks_common::util::hash; use stacks_common::util::secp256k1::{secp256k1_recover, secp256k1_verify, Secp256k1PublicKey}; -use stacks_common::util::secp256r1::secp256r1_verify; +use stacks_common::util::secp256r1::{secp256r1_verify, secp256r1_verify_digest}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; @@ -374,7 +374,12 @@ pub fn special_secp256r1_verify( } }; - Ok(Value::Bool( - secp256r1_verify(message, signature, pubkey).is_ok(), - )) + let version = *env.contract_context.get_clarity_version(); + let verify_result = if version.uses_secp256r1_double_hashing() { + secp256r1_verify(message, signature, pubkey) + } else { + secp256r1_verify_digest(message, signature, pubkey) + }; + + Ok(Value::Bool(verify_result.is_ok())) } diff --git a/clarity/src/vm/version.rs b/clarity/src/vm/version.rs index 8b38563c41..84ab9d9435 100644 --- a/clarity/src/vm/version.rs +++ b/clarity/src/vm/version.rs @@ -53,6 +53,15 @@ impl ClarityVersion { StacksEpochId::Epoch33 => ClarityVersion::Clarity4, } } + + pub fn uses_secp256r1_double_hashing(&self) -> bool { + match self { + ClarityVersion::Clarity1 + | ClarityVersion::Clarity2 + | ClarityVersion::Clarity3 + | ClarityVersion::Clarity4 => true, + } + } } impl FromStr for ClarityVersion { diff --git a/stacks-common/src/util/secp256r1.rs b/stacks-common/src/util/secp256r1.rs index f344eb3f57..2076ae422f 100644 --- a/stacks-common/src/util/secp256r1.rs +++ b/stacks-common/src/util/secp256r1.rs @@ -13,6 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use p256::ecdsa::signature::hazmat::{PrehashSigner, PrehashVerifier}; use p256::ecdsa::signature::{Signer, Verifier}; use p256::ecdsa::{ Signature as P256Signature, SigningKey as P256SigningKey, VerifyingKey as P256VerifyingKey, @@ -173,6 +174,24 @@ impl Secp256r1PublicKey { return Err(Secp256r1Error::InvalidMessage); } + let p256_sig = sig + .to_p256_signature() + .map_err(|_| Secp256r1Error::InvalidSignature)?; + + // Verify the signature + self.key + .verify_prehash(msg_hash, &p256_sig) + .map_err(|_| Secp256r1Error::InvalidSignature) + } + + /// Verify a signature against a message hash. The hash is SHA256 hashed + /// again before verification (i.e. double SHA256). + /// Returns Ok(()) if the signature is valid, or an error otherwise. + pub fn verify(&self, msg_hash: &[u8], sig: &MessageSignature) -> Result<(), Secp256r1Error> { + if msg_hash.len() != 32 { + return Err(Secp256r1Error::InvalidMessage); + } + let p256_sig = sig .to_p256_signature() .map_err(|_| Secp256r1Error::InvalidSignature)?; @@ -288,7 +307,8 @@ impl Secp256r1PrivateKey { bits } - /// Sign a message hash, returning the signature. + /// Sign a message hash, SHA256 hashing it (i.e. double-hashing) before + /// returning the signature. /// The message must be a 32-byte hash. pub fn sign(&self, data_hash: &[u8]) -> Result { if data_hash.len() != 32 { @@ -298,12 +318,26 @@ impl Secp256r1PrivateKey { let signature: P256Signature = self.key.sign(data_hash); Ok(MessageSignature::from_p256_signature(&signature)) } + + /// Sign a pre-hashed message, returning the signature without hashing again. + /// The digest must be a 32-byte hash. + pub fn sign_digest(&self, data_hash: &[u8]) -> Result { + if data_hash.len() != 32 { + return Err("Invalid message: must be a 32-byte hash"); + } + + let signature = self + .key + .sign_prehash(data_hash) + .map_err(|_| "Signing failed")?; + Ok(MessageSignature::from_p256_signature(&signature)) + } } /// Verify a secp256r1 signature. /// The message must be a 32-byte hash. /// The signature must be a 64-byte compact signature -pub fn secp256r1_verify( +pub fn secp256r1_verify_digest( message_arr: &[u8], signature_arr: &[u8], pubkey_arr: &[u8], @@ -320,6 +354,27 @@ pub fn secp256r1_verify( pk.verify_digest(msg, &sig) } +/// Verify a secp256r1 signature against the SHA256 hash of the message hash +/// (i.e., double-hashed). +/// The message must be a 32-byte hash. +/// The signature must be a 64-byte compact signature +pub fn secp256r1_verify( + message_arr: &[u8], + signature_arr: &[u8], + pubkey_arr: &[u8], +) -> Result<(), Secp256r1Error> { + let msg: &[u8; 32] = message_arr + .try_into() + .map_err(|_| Secp256r1Error::InvalidMessage)?; + let sig_bytes: &[u8; 64] = signature_arr + .try_into() + .map_err(|_| Secp256r1Error::InvalidSignature)?; + + let pk = Secp256r1PublicKey::from_slice(pubkey_arr).map_err(|_| Secp256r1Error::InvalidKey)?; + let sig = MessageSignature::from_bytes(sig_bytes).ok_or(Secp256r1Error::InvalidSignature)?; + pk.verify(msg, &sig) +} + #[cfg(test)] mod tests { use super::*; @@ -423,7 +478,7 @@ mod tests { let msg = b"hello world"; let msg_hash = Sha256Sum::from_data(msg).as_bytes().to_vec(); - let sig = privk.sign(&msg_hash).unwrap(); + let sig = privk.sign_digest(&msg_hash).unwrap(); pubk.verify_digest(&msg_hash, &sig) .expect("invalid signature"); } @@ -437,13 +492,61 @@ mod tests { let msg = b"hello world"; let msg_hash = Sha256Sum::from_data(msg).as_bytes().to_vec(); - let sig = privk1.sign(&msg_hash).unwrap(); + let sig = privk1.sign_digest(&msg_hash).unwrap(); let e = pubk2 .verify_digest(&msg_hash, &sig) .expect_err("expected an error"); assert_eq!(e, Secp256r1Error::InvalidSignature); } + #[test] + fn test_verify_digest_rejects_double_hashed_signature() { + let privk = Secp256r1PrivateKey::random(); + let pubk = Secp256r1PublicKey::from_private(&privk); + let msg_hash = Sha256Sum::from_data(b"double hash test") + .as_bytes() + .to_vec(); + + let sig = privk.sign(&msg_hash).unwrap(); + let err = pubk + .verify_digest(&msg_hash, &sig) + .expect_err("double-hashed signature should fail digest verify"); + assert_eq!(err, Secp256r1Error::InvalidSignature); + } + + #[test] + fn test_verify_rejects_single_hash_signature() { + let privk = Secp256r1PrivateKey::random(); + let pubk = Secp256r1PublicKey::from_private(&privk); + let msg_hash = Sha256Sum::from_data(b"single hash test") + .as_bytes() + .to_vec(); + + let sig = privk.sign_digest(&msg_hash).unwrap(); + let err = pubk + .verify(&msg_hash, &sig) + .expect_err("single-hash signature should fail double-hash verify"); + assert_eq!(err, Secp256r1Error::InvalidSignature); + } + + #[test] + fn test_secp256r1_verify_digest_function() { + let privk = Secp256r1PrivateKey::random(); + let pubk = Secp256r1PublicKey::from_private(&privk); + let msg_hash = Sha256Sum::from_data(b"function verify digest") + .as_bytes() + .to_vec(); + + let sig = privk.sign_digest(&msg_hash).unwrap(); + let signature_bytes = sig.0; + let pubkey_bytes = pubk.to_bytes(); + + assert!( + secp256r1_verify_digest(&msg_hash, &signature_bytes, &pubkey_bytes).is_ok(), + "secp256r1_verify_digest should accept valid pre-hashed signatures" + ); + } + #[test] fn test_public_key_compression() { let privk = Secp256r1PrivateKey::random(); From a83b2ea35b56f23a70ee020beb02616e292b83bb Mon Sep 17 00:00:00 2001 From: Brice Dobry <232827048+brice-stacks@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:47:47 -0500 Subject: [PATCH 2/4] docs: update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0985d33202..69f253bc6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE ## [Unreleased] +### Fixed + +- Updated the documentation for `secp256r1-verify` to match the implementation. The message hash passed to `secp256r1-verify` is SHA256 hashed again before verifying the signature. + +## [3.3.0.0.3] + ### Added - In the `/v3/transaction/{txid}` RPC endpoint, added `block_height` and `is_canonical` to the response. From d272eb8dd49e60bd89a3ab0f2f2eb9e01182217a Mon Sep 17 00:00:00 2001 From: Brice Dobry <232827048+brice-stacks@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:26:00 -0500 Subject: [PATCH 3/4] docs: reorder `secp256r1-verify` documentation --- clarity/src/vm/docs/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clarity/src/vm/docs/mod.rs b/clarity/src/vm/docs/mod.rs index dfcacf88fb..745429e286 100644 --- a/clarity/src/vm/docs/mod.rs +++ b/clarity/src/vm/docs/mod.rs @@ -1409,8 +1409,9 @@ const SECP256R1VERIFY_API: SpecialAPI = SpecialAPI { signature: "(secp256r1-verify message-hash signature public-key)", description: "The `secp256r1-verify` function verifies that the provided signature of the message-hash was signed with the private key that generated the public key. +In Clarity 4, the `message-hash` is SHA256 hashed again internally before verification (i.e. double SHA256). `message-hash` is typically the `sha256` of a message and `signature` is the raw 64-byte signature. -High-S signatures are allowed. In Clarity 4, the `message-hash` is SHA256 hashed again internally before verification (i.e. double SHA256). +High-S signatures are allowed. Note that this is NOT the Bitcoin (or default Stacks) signature scheme, secp256k1, but rather the NIST P-256 curve (also known as secp256r1).", example: "(secp256r1-verify 0xc3abef6a775793dfbc8e0719e7a1de1fc2f90d37a7912b1ce8e300a5a03b06a8 From 8b8451ae506d50b2ad6841940ef738cc91f68a33 Mon Sep 17 00:00:00 2001 From: Brice Dobry <232827048+brice-stacks@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:48:33 -0500 Subject: [PATCH 4/4] test: add NIST test vectors for `secp256r1-verify` testing --- clarity/src/vm/tests/crypto.rs | 181 +++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/clarity/src/vm/tests/crypto.rs b/clarity/src/vm/tests/crypto.rs index 05d9460320..00cce572ce 100644 --- a/clarity/src/vm/tests/crypto.rs +++ b/clarity/src/vm/tests/crypto.rs @@ -10,6 +10,187 @@ use stacks_common::util::secp256r1::{Secp256r1PrivateKey, Secp256r1PublicKey}; use crate::vm::types::{ResponseData, TypeSignature, Value}; use crate::vm::{execute_with_parameters, ClarityVersion}; +struct NistVector { + msg: &'static str, + d: &'static str, + q_x: &'static str, + q_y: &'static str, + k: &'static str, + r: &'static str, + s: &'static str, +} + +// Test vectors from NIST, +// https://csrc.nist.gov/Projects/cryptographic-algorithm-validation-program/Component-Testing +static NIST_VECTORS: &[NistVector] = &[ + NistVector { + msg: "44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56", + d: "519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464", + q_x: "1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83", + q_y: "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9", + k: "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", + r: "f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac", + s: "8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903", + }, + NistVector { + msg: "9b2db89cb0e8fa3cc7608b4d6cc1dec0114e0b9ff4080bea12b134f489ab2bbc", + d: "0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813", + q_x: "e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8a", + q_y: "bfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39", + k: "6d3e71882c3b83b156bb14e0ab184aa9fb728068d3ae9fac421187ae0b2f34c6", + r: "976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db", + s: "1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932", + }, + NistVector { + msg: "b804cf88af0c2eff8bbbfb3660ebb3294138e9d3ebd458884e19818061dacff0", + d: "e283871239837e13b95f789e6e1af63bf61c918c992e62bca040d64cad1fc2ef", + q_x: "74ccd8a62fba0e667c50929a53f78c21b8ff0c3c737b0b40b1750b2302b0bde8", + q_y: "29074e21f3a0ef88b9efdf10d06aa4c295cc1671f758ca0e4cd108803d0f2614", + k: "ad5e887eb2b380b8d8280ad6e5ff8a60f4d26243e0124c2f31a297b5d0835de2", + r: "35fb60f5ca0f3ca08542fb3cc641c8263a2cab7a90ee6a5e1583fac2bb6f6bd1", + s: "ee59d81bc9db1055cc0ed97b159d8784af04e98511d0a9a407b99bb292572e96", + }, + NistVector { + msg: "85b957d92766235e7c880ac5447cfbe97f3cb499f486d1e43bcb5c2ff9608a1a", + d: "a3d2d3b7596f6592ce98b4bfe10d41837f10027a90d7bb75349490018cf72d07", + q_x: "322f80371bf6e044bc49391d97c1714ab87f990b949bc178cb7c43b7c22d89e1", + q_y: "3c15d54a5cc6b9f09de8457e873eb3deb1fceb54b0b295da6050294fae7fd999", + k: "24fc90e1da13f17ef9fe84cc96b9471ed1aaac17e3a4bae33a115df4e5834f18", + r: "d7c562370af617b581c84a2468cc8bd50bb1cbf322de41b7887ce07c0e5884ca", + s: "b46d9f2d8c4bf83546ff178f1d78937c008d64e8ecc5cbb825cb21d94d670d89", + }, + NistVector { + msg: "3360d699222f21840827cf698d7cb635bee57dc80cd7733b682d41b55b666e22", + d: "53a0e8a8fe93db01e7ae94e1a9882a102ebd079b3a535827d583626c272d280d", + q_x: "1bcec4570e1ec2436596b8ded58f60c3b1ebc6a403bc5543040ba82963057244", + q_y: "8af62a4c683f096b28558320737bf83b9959a46ad2521004ef74cf85e67494e1", + k: "5d833e8d24cc7a402d7ee7ec852a3587cddeb48358cea71b0bedb8fabe84e0c4", + r: "18caaf7b663507a8bcd992b836dec9dc5703c080af5e51dfa3a9a7c387182604", + s: "77c68928ac3b88d985fb43fb615fb7ff45c18ba5c81af796c613dfa98352d29c", + }, + NistVector { + msg: "c413c4908cd0bc6d8e32001aa103043b2cf5be7fcbd61a5cec9488c3a577ca57", + d: "4af107e8e2194c830ffb712a65511bc9186a133007855b49ab4b3833aefc4a1d", + q_x: "a32e50be3dae2c8ba3f5e4bdae14cf7645420d425ead94036c22dd6c4fc59e00", + q_y: "d623bf641160c289d6742c6257ae6ba574446dd1d0e74db3aaa80900b78d4ae9", + k: "e18f96f84dfa2fd3cdfaec9159d4c338cd54ad314134f0b31e20591fc238d0ab", + r: "8524c5024e2d9a73bde8c72d9129f57873bbad0ed05215a372a84fdbc78f2e68", + s: "d18c2caf3b1072f87064ec5e8953f51301cada03469c640244760328eb5a05cb", + }, + NistVector { + msg: "88fc1e7d849794fc51b135fa135deec0db02b86c3cd8cebdaa79e8689e5b2898", + d: "78dfaa09f1076850b3e206e477494cddcfb822aaa0128475053592c48ebaf4ab", + q_x: "8bcfe2a721ca6d753968f564ec4315be4857e28bef1908f61a366b1f03c97479", + q_y: "0f67576a30b8e20d4232d8530b52fb4c89cbc589ede291e499ddd15fe870ab96", + k: "295544dbb2da3da170741c9b2c6551d40af7ed4e891445f11a02b66a5c258a77", + r: "c5a186d72df452015480f7f338970bfe825087f05c0088d95305f87aacc9b254", + s: "84a58f9e9d9e735344b316b1aa1ab5185665b85147dc82d92e969d7bee31ca30", + }, + NistVector { + msg: "41fa8d8b4cd0a5fdf021f4e4829d6d1e996bab6b4a19dcb85585fe76c582d2bc", + d: "80e692e3eb9fcd8c7d44e7de9f7a5952686407f90025a1d87e52c7096a62618a", + q_x: "a88bc8430279c8c0400a77d751f26c0abc93e5de4ad9a4166357952fe041e767", + q_y: "2d365a1eef25ead579cc9a069b6abc1b16b81c35f18785ce26a10ba6d1381185", + k: "7c80fd66d62cc076cef2d030c17c0a69c99611549cb32c4ff662475adbe84b22", + r: "9d0c6afb6df3bced455b459cc21387e14929392664bb8741a3693a1795ca6902", + s: "d7f9ddd191f1f412869429209ee3814c75c72fa46a9cccf804a2f5cc0b7e739f", + }, + NistVector { + msg: "2d72947c1731543b3d62490866a893952736757746d9bae13e719079299ae192", + d: "5e666c0db0214c3b627a8e48541cc84a8b6fd15f300da4dff5d18aec6c55b881", + q_x: "1bc487570f040dc94196c9befe8ab2b6de77208b1f38bdaae28f9645c4d2bc3a", + q_y: "ec81602abd8345e71867c8210313737865b8aa186851e1b48eaca140320f5d8f", + k: "2e7625a48874d86c9e467f890aaa7cd6ebdf71c0102bfdcfa24565d6af3fdce9", + r: "2f9e2b4e9f747c657f705bffd124ee178bbc5391c86d056717b140c153570fd9", + s: "f5413bfd85949da8d83de83ab0d19b2986613e224d1901d76919de23ccd03199", + }, + NistVector { + msg: "e138bd577c3729d0e24a98a82478bcc7482499c4cdf734a874f7208ddbc3c116", + d: "f73f455271c877c4d5334627e37c278f68d143014b0a05aa62f308b2101c5308", + q_x: "b8188bd68701fc396dab53125d4d28ea33a91daf6d21485f4770f6ea8c565dde", + q_y: "423f058810f277f8fe076f6db56e9285a1bf2c2a1dae145095edd9c04970bc4a", + k: "62f8665fd6e26b3fa069e85281777a9b1f0dfd2c0b9f54a086d0c109ff9fd615", + r: "1cc628533d0004b2b20e7f4baad0b8bb5e0673db159bbccf92491aef61fc9620", + s: "880e0bbf82a8cf818ed46ba03cf0fc6c898e36fca36cc7fdb1d2db7503634430", + }, +]; + +#[test] +fn secp256r1_verify_valid_signatures_nist() { + use stacks_common::util::hash::hex_bytes; + use stacks_common::util::secp256r1::MessageSignature; + + for NistVector { + msg, + d, + q_x, + q_y, + k, + r, + s, + } in NIST_VECTORS + { + let message_hash = hex_bytes(msg).unwrap(); + let privk = Secp256r1PrivateKey::from_hex(d).unwrap(); + let mut pubk = Secp256r1PublicKey::from_hex(&format!("04{q_x}{q_y}")).unwrap(); + pubk.set_compressed(true); + + let signature_dh = privk.sign(&message_hash).unwrap(); + let signature_nist = MessageSignature::from_hex(&format!("{r}{s}")).unwrap(); + + let verified_double_hash = pubk.verify(&message_hash, &signature_dh).is_ok(); + let verified_nist_sign = pubk.verify_digest(&message_hash, &signature_nist).is_ok(); + + info!( + "Signed with SK"; + "nist_signature" => format!("{r}{s}"), + "double_hash" => to_hex(&signature_dh.0), + "pubk" => to_hex(&pubk.to_bytes()), + "verified_double_hash" => verified_double_hash, + "verified_nist_sign" => verified_nist_sign, + ); + + let program = format!( + "(secp256r1-verify {} {} {})", + buff_literal(&message_hash), + buff_literal(&signature_dh.0), + buff_literal(&pubk.to_bytes()) + ); + + assert_eq!( + Value::Bool(true), + execute_with_parameters( + program.as_str(), + ClarityVersion::Clarity4, + StacksEpochId::Epoch33, + false + ) + .expect("execution should succeed") + .expect("should return a value") + ); + + // TODO: Once implemented, check the NIST signature against the Clarity 5 function. + // let program = format!( + // "(secp256r1-verify {} {} {})", + // buff_literal(&message_hash), + // buff_literal(&signature_nist.0), + // buff_literal(&pubk.to_bytes()) + // ); + + // assert_eq!( + // Value::Bool(true), + // execute_with_parameters( + // program.as_str(), + // ClarityVersion::Clarity5, + // StacksEpochId::Epoch34, + // false + // ) + // .expect("execution should succeed") + // .expect("should return a value") + // ); + } +} + fn secp256r1_vectors() -> (Vec, Vec, Vec) { let privk = Secp256r1PrivateKey::from_seed(&[7u8; 32]); let pubk = Secp256r1PublicKey::from_private(&privk);