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