fedimint_core/encoding/
secp256k1.rs1use std::io::{Error, Read, Write};
2
3use crate::encoding::{Decodable, DecodeError, Encodable};
4use crate::module::registry::ModuleDecoderRegistry;
5
6impl Encodable for secp256k1::ecdsa::Signature {
7 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
8 let bytes = self.serialize_compact();
9 writer.write_all(&bytes)?;
10 Ok(())
11 }
12}
13
14impl Decodable for secp256k1::ecdsa::Signature {
15 fn consensus_decode_partial<D: std::io::Read>(
16 d: &mut D,
17 modules: &ModuleDecoderRegistry,
18 ) -> Result<Self, DecodeError> {
19 Self::from_compact(&<[u8; 64]>::consensus_decode_partial(d, modules)?)
20 .map_err(DecodeError::from_err)
21 }
22}
23
24impl Encodable for secp256k1::PublicKey {
25 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
26 self.serialize().consensus_encode(writer)
27 }
28}
29
30impl Decodable for secp256k1::PublicKey {
31 fn consensus_decode_partial<D: std::io::Read>(
32 d: &mut D,
33 modules: &ModuleDecoderRegistry,
34 ) -> Result<Self, DecodeError> {
35 Self::from_slice(&<[u8; 33]>::consensus_decode_partial(d, modules)?)
36 .map_err(DecodeError::from_err)
37 }
38}
39
40impl Encodable for secp256k1::XOnlyPublicKey {
41 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
42 self.serialize().consensus_encode(writer)
43 }
44}
45
46impl Decodable for secp256k1::XOnlyPublicKey {
47 fn consensus_decode_partial<D: std::io::Read>(
48 d: &mut D,
49 modules: &ModuleDecoderRegistry,
50 ) -> Result<Self, DecodeError> {
51 Self::from_slice(&<[u8; 32]>::consensus_decode_partial(d, modules)?)
52 .map_err(DecodeError::from_err)
53 }
54}
55
56impl Encodable for secp256k1::SecretKey {
57 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
58 self.secret_bytes().consensus_encode(writer)
59 }
60}
61
62impl Decodable for secp256k1::SecretKey {
63 fn consensus_decode_partial<D: std::io::Read>(
64 d: &mut D,
65 modules: &ModuleDecoderRegistry,
66 ) -> Result<Self, DecodeError> {
67 Self::from_slice(&<[u8; 32]>::consensus_decode_partial(d, modules)?)
68 .map_err(DecodeError::from_err)
69 }
70}
71
72impl Encodable for secp256k1::schnorr::Signature {
73 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
74 let bytes = &self[..];
75 assert_eq!(bytes.len(), secp256k1::constants::SCHNORR_SIGNATURE_SIZE);
76 writer.write_all(bytes)?;
77 Ok(())
78 }
79}
80
81impl Decodable for secp256k1::schnorr::Signature {
82 fn consensus_decode_partial<D: std::io::Read>(
83 d: &mut D,
84 modules: &ModuleDecoderRegistry,
85 ) -> Result<Self, DecodeError> {
86 let bytes = <[u8; secp256k1::constants::SCHNORR_SIGNATURE_SIZE]>::consensus_decode_partial(
87 d, modules,
88 )?;
89 Self::from_slice(&bytes).map_err(DecodeError::from_err)
90 }
91}
92
93impl Encodable for bitcoin::key::Keypair {
94 fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
95 self.secret_bytes().consensus_encode(writer)
96 }
97}
98
99impl Decodable for bitcoin::key::Keypair {
100 fn consensus_decode_partial<D: Read>(
101 d: &mut D,
102 modules: &ModuleDecoderRegistry,
103 ) -> Result<Self, DecodeError> {
104 let sec_bytes = <[u8; 32]>::consensus_decode_partial(d, modules)?;
105 Self::from_seckey_slice(bitcoin::secp256k1::global::SECP256K1, &sec_bytes) .map_err(DecodeError::from_err)
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use secp256k1::Message;
113 use secp256k1::hashes::Hash as BitcoinHash;
114
115 use super::super::tests::test_roundtrip;
116
117 #[test_log::test]
118 fn test_ecdsa_sig() {
119 let ctx = secp256k1::Secp256k1::new();
120 let (sk, _pk) = ctx.generate_keypair(&mut rand::thread_rng());
121 let sig = ctx.sign_ecdsa(
122 &Message::from_digest(*secp256k1::hashes::sha256::Hash::hash(b"Hello World!").as_ref()),
123 &sk,
124 );
125
126 test_roundtrip(&sig);
127 }
128
129 #[test_log::test]
130 fn test_schnorr_pub_key() {
131 let ctx = secp256k1::global::SECP256K1;
132 let mut rng = rand::rngs::OsRng;
133 let sec_key = bitcoin::key::Keypair::new(ctx, &mut rng);
134 let pub_key = sec_key.public_key();
135 test_roundtrip(&pub_key);
136
137 let sig = ctx.sign_schnorr(
138 &Message::from_digest(*secp256k1::hashes::sha256::Hash::hash(b"Hello World!").as_ref()),
139 &sec_key,
140 );
141
142 test_roundtrip(&sig);
143 }
144}