nut10.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. //! NUT-10: Spending conditions
  2. //!
  3. //! <https://github.com/cashubtc/nuts/blob/main/10.md>
  4. use core::str::FromStr;
  5. use serde::ser::SerializeTuple;
  6. use serde::{Deserialize, Serialize, Serializer};
  7. use crate::error::Error;
  8. #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
  9. pub enum Kind {
  10. /// NUT-11 P2PK
  11. #[default]
  12. P2PK,
  13. }
  14. #[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
  15. pub struct SecretData {
  16. /// Unique random string
  17. pub nonce: String,
  18. /// Expresses the spending condition specific to each kind
  19. pub data: String,
  20. /// Additional data committed to and can be used for feature extensions
  21. #[serde(skip_serializing_if = "Vec::is_empty")]
  22. pub tags: Vec<Vec<String>>,
  23. }
  24. #[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)]
  25. pub struct Secret {
  26. /// Kind of the spending condition
  27. pub kind: Kind,
  28. pub secret_data: SecretData,
  29. }
  30. impl Secret {
  31. pub fn new<S>(kind: Kind, data: S, tags: Vec<Vec<String>>) -> Self
  32. where
  33. S: Into<String>,
  34. {
  35. let nonce = crate::secret::Secret::generate().to_string();
  36. let secret_data = SecretData {
  37. nonce,
  38. data: data.into(),
  39. tags,
  40. };
  41. Self { kind, secret_data }
  42. }
  43. }
  44. impl Serialize for Secret {
  45. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  46. where
  47. S: Serializer,
  48. {
  49. // Create a tuple representing the struct fields
  50. let secret_tuple = (&self.kind, &self.secret_data);
  51. // Serialize the tuple as a JSON array
  52. let mut s = serializer.serialize_tuple(2)?;
  53. s.serialize_element(&secret_tuple.0)?;
  54. s.serialize_element(&secret_tuple.1)?;
  55. s.end()
  56. }
  57. }
  58. impl TryFrom<Secret> for crate::secret::Secret {
  59. type Error = Error;
  60. fn try_from(secret: Secret) -> Result<crate::secret::Secret, Self::Error> {
  61. Ok(crate::secret::Secret::from_str(&serde_json::to_string(
  62. &secret,
  63. )?)?)
  64. }
  65. }
  66. #[cfg(test)]
  67. mod tests {
  68. use std::assert_eq;
  69. use super::*;
  70. #[test]
  71. fn test_secret_serialize() {
  72. let secret = Secret {
  73. kind: Kind::P2PK,
  74. secret_data: SecretData {
  75. nonce: "5d11913ee0f92fefdc82a6764fd2457a".to_string(),
  76. data: "026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198"
  77. .to_string(),
  78. tags: vec![vec![
  79. "key".to_string(),
  80. "value1".to_string(),
  81. "value2".to_string(),
  82. ]],
  83. },
  84. };
  85. let secret_str = r#"["P2PK",{"nonce":"5d11913ee0f92fefdc82a6764fd2457a","data":"026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198","tags":[["key","value1","value2"]]}]"#;
  86. assert_eq!(serde_json::to_string(&secret).unwrap(), secret_str);
  87. }
  88. }