/ fedimint-core / src / core / backup.rs
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  }