add bip340 test vectors for public keys

This commit is contained in:
Sergio Chouhy 2025-08-12 15:20:35 -03:00
parent e8e565fe8c
commit 927254f6ce
5 changed files with 61 additions and 7 deletions

View File

@ -14,3 +14,4 @@ secp256k1 = "0.31.1"
[dev-dependencies]
test-program-methods = { path = "test_program_methods" }
hex = "0.4.3"

View File

@ -11,9 +11,9 @@ const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = b"NSSA/v0.1/
impl Message {
/// Serializes a `Message` into bytes in the following layout:
/// TAG || <program_id> (bytes LE) * 8 || addresses_len (4 bytes LE) || addresses (32 bytes * N) || nonces_len (4 bytes LE) || nonces (16 bytes * M) || instruction_data_len || instruction_data (4 bytes * K)
/// PREFIX || <program_id> (4 bytes LE) * 8 || addresses_len (4 bytes LE) || addresses (32 bytes * N) || nonces_len (4 bytes LE) || nonces (16 bytes LE * M) || instruction_data_len || instruction_data (4 bytes LE * K)
/// Integers and words are encoded in little-endian byte order, and fields appear in the above order.
pub(crate) fn message_to_bytes(&self) -> Vec<u8> {
pub(crate) fn to_bytes(&self) -> Vec<u8> {
let mut bytes = MESSAGE_ENCODING_PREFIX.to_vec();
// program_id: [u32; 8]
for word in &self.program_id {
@ -27,6 +27,7 @@ impl Message {
bytes.extend_from_slice(addr.value());
}
// nonces: Vec<u128>
// serialize length as u32 little endian, then all nonces concatenated in LE
let nonces_len = self.nonces.len() as u32;
bytes.extend(&nonces_len.to_le_bytes());
for nonce in &self.nonces {
@ -93,8 +94,8 @@ impl WitnessSet {
let size = self.signatures_and_public_keys.len() as u32;
bytes.extend_from_slice(&size.to_le_bytes());
for (signature, public_key) in &self.signatures_and_public_keys {
bytes.extend_from_slice(&signature.value);
bytes.extend_from_slice(&public_key.0);
bytes.extend_from_slice(signature.to_bytes());
bytes.extend_from_slice(public_key.to_bytes());
}
bytes
}
@ -120,7 +121,7 @@ impl WitnessSet {
impl PublicTransaction {
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = self.message.message_to_bytes();
let mut bytes = self.message.to_bytes();
bytes.extend_from_slice(&self.witness_set.to_bytes());
bytes
}

View File

@ -11,7 +11,7 @@ pub struct WitnessSet {
impl WitnessSet {
pub fn for_message(message: &Message, private_keys: &[&PrivateKey]) -> Self {
let message_bytes = message.message_to_bytes();
let message_bytes = message.to_bytes();
let signatures_and_public_keys = private_keys
.iter()
.map(|&key| (Signature::new(key, &message_bytes), PublicKey::new(key)))
@ -22,7 +22,7 @@ impl WitnessSet {
}
pub fn is_valid_for(&self, message: &Message) -> bool {
let message_bytes = message.message_to_bytes();
let message_bytes = message.to_bytes();
for (signature, public_key) in self.iter_signatures() {
if !signature.is_valid_for(&message_bytes, &public_key) {
return false;

View File

@ -10,6 +10,10 @@ impl PublicKey {
cursor.read_exact(&mut value).unwrap();
Self(value)
}
pub(crate) fn to_bytes(&self) -> &[u8] {
&self.0
}
}
impl Signature {
@ -19,4 +23,8 @@ impl Signature {
cursor.read_exact(&mut value).unwrap();
Self { value }
}
pub(crate) fn to_bytes(&self) -> &[u8] {
&self.value
}
}

View File

@ -21,3 +21,47 @@ impl PublicKey {
}
}
#[cfg(test)]
mod tests {
use crate::{PrivateKey, PublicKey};
fn hex_to_32_bytes(hex: &str) -> [u8; 32] {
hex::decode(hex).unwrap().try_into().unwrap()
}
/// Test vectors from
/// https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv
const BIP340_PK_TEST_VECTORS: [(&str, &str); 5] = [
(
"0000000000000000000000000000000000000000000000000000000000000003",
"F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
),
(
"B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF",
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
),
(
"C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9",
"DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8",
),
(
"0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710",
"25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517",
),
(
"0340034003400340034003400340034003400340034003400340034003400340",
"778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117",
),
];
#[test]
fn test_bip340_pk_test_vectors() {
for (i, (private_key_hex, expected_public_key_hex)) in
BIP340_PK_TEST_VECTORS.iter().enumerate()
{
let key = PrivateKey::try_new(hex_to_32_bytes(private_key_hex)).unwrap();
let public_key = PublicKey::new(&key);
let expected_public_key = PublicKey(hex_to_32_bytes(expected_public_key_hex));
assert_eq!(public_key, expected_public_key, "Failed test vector at index {i}");
}
}
}