backup.rs
1 use std::fmt::Debug; 2 3 use bitcoin::secp256k1; 4 use bitcoin_hashes::{sha256, Hash}; 5 use fedimint_core::encoding::{Decodable, Encodable}; 6 use secp256k1::{Secp256k1, Signing, Verification}; 7 use secp256k1_zkp::{KeyPair, Message}; 8 use serde::{Deserialize, Serialize}; 9 10 /// Maximum payload size of a backup request 11 /// 12 /// Note: this is just a current hard limit, 13 /// that could be changed in the future versions. 14 /// 15 /// For comparison - at the time of writing, ecash module 16 /// backup with 52 notes is around 5.1K. 17 pub const BACKUP_REQUEST_MAX_PAYLOAD_SIZE_BYTES: usize = 128 * 1024; 18 19 #[derive(Debug, Serialize, Deserialize, Encodable, Decodable)] 20 pub struct BackupRequest { 21 pub id: secp256k1::PublicKey, 22 #[serde(with = "fedimint_core::hex::serde")] 23 pub payload: Vec<u8>, 24 pub timestamp: std::time::SystemTime, 25 } 26 27 impl BackupRequest { 28 fn hash(&self) -> sha256::Hash { 29 self.consensus_hash() 30 } 31 32 pub fn sign(self, keypair: &KeyPair) -> anyhow::Result<SignedBackupRequest> { 33 let signature = secp256k1::SECP256K1.sign_schnorr(&Message::from(self.hash()), keypair); 34 35 Ok(SignedBackupRequest { 36 request: self, 37 signature, 38 }) 39 } 40 } 41 42 #[derive(Debug, Serialize, Deserialize)] 43 pub struct SignedBackupRequest { 44 #[serde(flatten)] 45 request: BackupRequest, 46 pub signature: secp256k1::schnorr::Signature, 47 } 48 49 impl SignedBackupRequest { 50 pub fn verify_valid<C>(&self, ctx: &Secp256k1<C>) -> Result<&BackupRequest, secp256k1::Error> 51 where 52 C: Signing + Verification, 53 { 54 ctx.verify_schnorr( 55 &self.signature, 56 &Message::from_slice(&self.request.hash().to_byte_array()).expect("Can't fail"), 57 &self.request.id.x_only_public_key().0, 58 )?; 59 60 Ok(&self.request) 61 } 62 }