mod.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. //! NUT-00: Notation and Models
  2. //!
  3. //! <https://github.com/cashubtc/nuts/blob/main/00.md>
  4. use std::cmp::Ordering;
  5. use std::collections::{HashMap, HashSet};
  6. use std::fmt;
  7. use std::hash::{Hash, Hasher};
  8. use std::str::FromStr;
  9. use std::string::FromUtf8Error;
  10. use serde::{de, Deserialize, Deserializer, Serialize};
  11. use thiserror::Error;
  12. #[cfg(feature = "wallet")]
  13. use super::nut10;
  14. #[cfg(feature = "wallet")]
  15. use super::nut11::SpendingConditions;
  16. #[cfg(feature = "wallet")]
  17. use crate::amount::SplitTarget;
  18. #[cfg(feature = "wallet")]
  19. use crate::dhke::blind_message;
  20. use crate::dhke::hash_to_curve;
  21. use crate::nuts::nut01::PublicKey;
  22. #[cfg(feature = "wallet")]
  23. use crate::nuts::nut01::SecretKey;
  24. use crate::nuts::nut11::{serde_p2pk_witness, P2PKWitness};
  25. use crate::nuts::nut12::BlindSignatureDleq;
  26. use crate::nuts::nut14::{serde_htlc_witness, HTLCWitness};
  27. use crate::nuts::{Id, ProofDleq};
  28. use crate::secret::Secret;
  29. use crate::Amount;
  30. pub mod token;
  31. pub use token::{Token, TokenV3, TokenV4};
  32. /// List of [Proof]
  33. pub type Proofs = Vec<Proof>;
  34. /// Utility methods for [Proofs]
  35. pub trait ProofsMethods {
  36. /// Count proofs by keyset
  37. fn count_by_keyset(&self) -> HashMap<Id, u64>;
  38. /// Sum proofs by keyset
  39. fn sum_by_keyset(&self) -> HashMap<Id, Amount>;
  40. /// Try to sum up the amounts of all [Proof]s
  41. fn total_amount(&self) -> Result<Amount, Error>;
  42. /// Try to fetch the pubkeys of all [Proof]s
  43. fn ys(&self) -> Result<Vec<PublicKey>, Error>;
  44. /// Create a copy of proofs without dleqs
  45. fn without_dleqs(&self) -> Proofs;
  46. }
  47. impl ProofsMethods for Proofs {
  48. fn count_by_keyset(&self) -> HashMap<Id, u64> {
  49. count_by_keyset(self.iter())
  50. }
  51. fn sum_by_keyset(&self) -> HashMap<Id, Amount> {
  52. sum_by_keyset(self.iter())
  53. }
  54. fn total_amount(&self) -> Result<Amount, Error> {
  55. total_amount(self.iter())
  56. }
  57. fn ys(&self) -> Result<Vec<PublicKey>, Error> {
  58. ys(self.iter())
  59. }
  60. fn without_dleqs(&self) -> Proofs {
  61. self.iter()
  62. .map(|p| {
  63. let mut p = p.clone();
  64. p.dleq = None;
  65. p
  66. })
  67. .collect()
  68. }
  69. }
  70. impl ProofsMethods for HashSet<Proof> {
  71. fn count_by_keyset(&self) -> HashMap<Id, u64> {
  72. count_by_keyset(self.iter())
  73. }
  74. fn sum_by_keyset(&self) -> HashMap<Id, Amount> {
  75. sum_by_keyset(self.iter())
  76. }
  77. fn total_amount(&self) -> Result<Amount, Error> {
  78. total_amount(self.iter())
  79. }
  80. fn ys(&self) -> Result<Vec<PublicKey>, Error> {
  81. ys(self.iter())
  82. }
  83. fn without_dleqs(&self) -> Proofs {
  84. self.iter()
  85. .map(|p| {
  86. let mut p = p.clone();
  87. p.dleq = None;
  88. p
  89. })
  90. .collect()
  91. }
  92. }
  93. fn count_by_keyset<'a, I: Iterator<Item = &'a Proof>>(proofs: I) -> HashMap<Id, u64> {
  94. let mut counts = HashMap::new();
  95. for proof in proofs {
  96. *counts.entry(proof.keyset_id).or_insert(0) += 1;
  97. }
  98. counts
  99. }
  100. fn sum_by_keyset<'a, I: Iterator<Item = &'a Proof>>(proofs: I) -> HashMap<Id, Amount> {
  101. let mut sums = HashMap::new();
  102. for proof in proofs {
  103. *sums.entry(proof.keyset_id).or_insert(Amount::ZERO) += proof.amount;
  104. }
  105. sums
  106. }
  107. fn total_amount<'a, I: Iterator<Item = &'a Proof>>(proofs: I) -> Result<Amount, Error> {
  108. Amount::try_sum(proofs.map(|p| p.amount)).map_err(Into::into)
  109. }
  110. fn ys<'a, I: Iterator<Item = &'a Proof>>(proofs: I) -> Result<Vec<PublicKey>, Error> {
  111. proofs.map(|p| p.y()).collect::<Result<Vec<PublicKey>, _>>()
  112. }
  113. /// NUT00 Error
  114. #[derive(Debug, Error)]
  115. pub enum Error {
  116. /// Proofs required
  117. #[error("Proofs required in token")]
  118. ProofsRequired,
  119. /// Unsupported token
  120. #[error("Unsupported token")]
  121. UnsupportedToken,
  122. /// Unsupported token
  123. #[error("Unsupported unit")]
  124. UnsupportedUnit,
  125. /// Unsupported token
  126. #[error("Unsupported payment method")]
  127. UnsupportedPaymentMethod,
  128. /// Duplicate proofs in token
  129. #[error("Duplicate proofs in token")]
  130. DuplicateProofs,
  131. /// Serde Json error
  132. #[error(transparent)]
  133. SerdeJsonError(#[from] serde_json::Error),
  134. /// Utf8 parse error
  135. #[error(transparent)]
  136. Utf8ParseError(#[from] FromUtf8Error),
  137. /// Base64 error
  138. #[error(transparent)]
  139. Base64Error(#[from] bitcoin::base64::DecodeError),
  140. /// Ciborium deserialization error
  141. #[error(transparent)]
  142. CiboriumError(#[from] ciborium::de::Error<std::io::Error>),
  143. /// Ciborium serialization error
  144. #[error(transparent)]
  145. CiboriumSerError(#[from] ciborium::ser::Error<std::io::Error>),
  146. /// Amount Error
  147. #[error(transparent)]
  148. Amount(#[from] crate::amount::Error),
  149. /// Secret error
  150. #[error(transparent)]
  151. Secret(#[from] crate::secret::Error),
  152. /// DHKE error
  153. #[error(transparent)]
  154. DHKE(#[from] crate::dhke::Error),
  155. /// NUT10 error
  156. #[error(transparent)]
  157. NUT10(#[from] crate::nuts::nut10::Error),
  158. /// NUT11 error
  159. #[error(transparent)]
  160. NUT11(#[from] crate::nuts::nut11::Error),
  161. }
  162. /// Blinded Message (also called `output`)
  163. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  164. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  165. pub struct BlindedMessage {
  166. /// Amount
  167. ///
  168. /// The value for the requested [BlindSignature]
  169. pub amount: Amount,
  170. /// Keyset ID
  171. ///
  172. /// ID from which we expect a signature.
  173. #[serde(rename = "id")]
  174. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  175. pub keyset_id: Id,
  176. /// Blinded secret message (B_)
  177. ///
  178. /// The blinded secret message generated by the sender.
  179. #[serde(rename = "B_")]
  180. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  181. pub blinded_secret: PublicKey,
  182. /// Witness
  183. ///
  184. /// <https://github.com/cashubtc/nuts/blob/main/11.md>
  185. #[serde(skip_serializing_if = "Option::is_none")]
  186. pub witness: Option<Witness>,
  187. }
  188. impl BlindedMessage {
  189. /// Compose new blinded message
  190. #[inline]
  191. pub fn new(amount: Amount, keyset_id: Id, blinded_secret: PublicKey) -> Self {
  192. Self {
  193. amount,
  194. keyset_id,
  195. blinded_secret,
  196. witness: None,
  197. }
  198. }
  199. /// Add witness
  200. #[inline]
  201. pub fn witness(&mut self, witness: Witness) {
  202. self.witness = Some(witness);
  203. }
  204. }
  205. /// Blind Signature (also called `promise`)
  206. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
  207. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  208. pub struct BlindSignature {
  209. /// Amount
  210. ///
  211. /// The value of the blinded token.
  212. pub amount: Amount,
  213. /// Keyset ID
  214. ///
  215. /// ID of the mint keys that signed the token.
  216. #[serde(rename = "id")]
  217. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  218. pub keyset_id: Id,
  219. /// Blinded signature (C_)
  220. ///
  221. /// The blinded signature on the secret message `B_` of [BlindedMessage].
  222. #[serde(rename = "C_")]
  223. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  224. pub c: PublicKey,
  225. /// DLEQ Proof
  226. ///
  227. /// <https://github.com/cashubtc/nuts/blob/main/12.md>
  228. #[serde(skip_serializing_if = "Option::is_none")]
  229. pub dleq: Option<BlindSignatureDleq>,
  230. }
  231. impl Ord for BlindSignature {
  232. fn cmp(&self, other: &Self) -> Ordering {
  233. self.amount.cmp(&other.amount)
  234. }
  235. }
  236. impl PartialOrd for BlindSignature {
  237. fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  238. Some(self.cmp(other))
  239. }
  240. }
  241. /// Witness
  242. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  243. #[serde(untagged)]
  244. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  245. pub enum Witness {
  246. /// P2PK Witness
  247. #[serde(with = "serde_p2pk_witness")]
  248. P2PKWitness(P2PKWitness),
  249. /// HTLC Witness
  250. #[serde(with = "serde_htlc_witness")]
  251. HTLCWitness(HTLCWitness),
  252. }
  253. impl From<P2PKWitness> for Witness {
  254. fn from(witness: P2PKWitness) -> Self {
  255. Self::P2PKWitness(witness)
  256. }
  257. }
  258. impl From<HTLCWitness> for Witness {
  259. fn from(witness: HTLCWitness) -> Self {
  260. Self::HTLCWitness(witness)
  261. }
  262. }
  263. impl Witness {
  264. /// Add signatures to [`Witness`]
  265. pub fn add_signatures(&mut self, signatues: Vec<String>) {
  266. match self {
  267. Self::P2PKWitness(p2pk_witness) => p2pk_witness.signatures.extend(signatues),
  268. Self::HTLCWitness(htlc_witness) => {
  269. htlc_witness.signatures = htlc_witness.signatures.clone().map(|sigs| {
  270. let mut sigs = sigs;
  271. sigs.extend(signatues);
  272. sigs
  273. });
  274. }
  275. }
  276. }
  277. /// Get signatures on [`Witness`]
  278. pub fn signatures(&self) -> Option<Vec<String>> {
  279. match self {
  280. Self::P2PKWitness(witness) => Some(witness.signatures.clone()),
  281. Self::HTLCWitness(witness) => witness.signatures.clone(),
  282. }
  283. }
  284. /// Get preimage from [`Witness`]
  285. pub fn preimage(&self) -> Option<String> {
  286. match self {
  287. Self::P2PKWitness(_witness) => None,
  288. Self::HTLCWitness(witness) => Some(witness.preimage.clone()),
  289. }
  290. }
  291. }
  292. /// Proofs
  293. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
  294. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  295. pub struct Proof {
  296. /// Amount
  297. pub amount: Amount,
  298. /// `Keyset id`
  299. #[serde(rename = "id")]
  300. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  301. pub keyset_id: Id,
  302. /// Secret message
  303. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  304. pub secret: Secret,
  305. /// Unblinded signature
  306. #[serde(rename = "C")]
  307. #[cfg_attr(feature = "swagger", schema(value_type = String))]
  308. pub c: PublicKey,
  309. /// Witness
  310. #[serde(skip_serializing_if = "Option::is_none")]
  311. pub witness: Option<Witness>,
  312. /// DLEQ Proof
  313. #[serde(skip_serializing_if = "Option::is_none")]
  314. pub dleq: Option<ProofDleq>,
  315. }
  316. impl Proof {
  317. /// Create new [`Proof`]
  318. pub fn new(amount: Amount, keyset_id: Id, secret: Secret, c: PublicKey) -> Self {
  319. Proof {
  320. amount,
  321. keyset_id,
  322. secret,
  323. c,
  324. witness: None,
  325. dleq: None,
  326. }
  327. }
  328. /// Check if proof is in active keyset `Id`s
  329. pub fn is_active(&self, active_keyset_ids: &[Id]) -> bool {
  330. active_keyset_ids.contains(&self.keyset_id)
  331. }
  332. /// Get y from proof
  333. ///
  334. /// Where y is `hash_to_curve(secret)`
  335. pub fn y(&self) -> Result<PublicKey, Error> {
  336. Ok(hash_to_curve(self.secret.as_bytes())?)
  337. }
  338. }
  339. impl Hash for Proof {
  340. fn hash<H: Hasher>(&self, state: &mut H) {
  341. self.secret.hash(state);
  342. }
  343. }
  344. impl Ord for Proof {
  345. fn cmp(&self, other: &Self) -> std::cmp::Ordering {
  346. self.amount.cmp(&other.amount)
  347. }
  348. }
  349. impl PartialOrd for Proof {
  350. fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
  351. Some(self.cmp(other))
  352. }
  353. }
  354. /// Proof V4
  355. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
  356. pub struct ProofV4 {
  357. /// Amount in satoshi
  358. #[serde(rename = "a")]
  359. pub amount: Amount,
  360. /// Secret message
  361. #[serde(rename = "s")]
  362. pub secret: Secret,
  363. /// Unblinded signature
  364. #[serde(
  365. serialize_with = "serialize_v4_pubkey",
  366. deserialize_with = "deserialize_v4_pubkey"
  367. )]
  368. pub c: PublicKey,
  369. /// Witness
  370. #[serde(default)]
  371. #[serde(skip_serializing_if = "Option::is_none")]
  372. pub witness: Option<Witness>,
  373. /// DLEQ Proof
  374. #[serde(rename = "d")]
  375. pub dleq: Option<ProofDleq>,
  376. }
  377. impl ProofV4 {
  378. /// [`ProofV4`] into [`Proof`]
  379. pub fn into_proof(&self, keyset_id: &Id) -> Proof {
  380. Proof {
  381. amount: self.amount,
  382. keyset_id: *keyset_id,
  383. secret: self.secret.clone(),
  384. c: self.c,
  385. witness: self.witness.clone(),
  386. dleq: self.dleq.clone(),
  387. }
  388. }
  389. }
  390. impl From<Proof> for ProofV4 {
  391. fn from(proof: Proof) -> ProofV4 {
  392. let Proof {
  393. amount,
  394. keyset_id: _,
  395. secret,
  396. c,
  397. witness,
  398. dleq,
  399. } = proof;
  400. ProofV4 {
  401. amount,
  402. secret,
  403. c,
  404. witness,
  405. dleq,
  406. }
  407. }
  408. }
  409. fn serialize_v4_pubkey<S>(key: &PublicKey, serializer: S) -> Result<S::Ok, S::Error>
  410. where
  411. S: serde::Serializer,
  412. {
  413. serializer.serialize_bytes(&key.to_bytes())
  414. }
  415. fn deserialize_v4_pubkey<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
  416. where
  417. D: serde::Deserializer<'de>,
  418. {
  419. let bytes = Vec::<u8>::deserialize(deserializer)?;
  420. PublicKey::from_slice(&bytes).map_err(serde::de::Error::custom)
  421. }
  422. /// Currency Unit
  423. #[non_exhaustive]
  424. #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
  425. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  426. pub enum CurrencyUnit {
  427. /// Sat
  428. #[default]
  429. Sat,
  430. /// Msat
  431. Msat,
  432. /// Usd
  433. Usd,
  434. /// Euro
  435. Eur,
  436. /// Auth
  437. Auth,
  438. /// Custom currency unit
  439. Custom(String),
  440. }
  441. #[cfg(feature = "mint")]
  442. impl CurrencyUnit {
  443. /// Derivation index mint will use for unit
  444. pub fn derivation_index(&self) -> Option<u32> {
  445. match self {
  446. Self::Sat => Some(0),
  447. Self::Msat => Some(1),
  448. Self::Usd => Some(2),
  449. Self::Eur => Some(3),
  450. Self::Auth => Some(4),
  451. _ => None,
  452. }
  453. }
  454. }
  455. impl FromStr for CurrencyUnit {
  456. type Err = Error;
  457. fn from_str(value: &str) -> Result<Self, Self::Err> {
  458. let value = &value.to_uppercase();
  459. match value.as_str() {
  460. "SAT" => Ok(Self::Sat),
  461. "MSAT" => Ok(Self::Msat),
  462. "USD" => Ok(Self::Usd),
  463. "EUR" => Ok(Self::Eur),
  464. "AUTH" => Ok(Self::Auth),
  465. c => Ok(Self::Custom(c.to_string())),
  466. }
  467. }
  468. }
  469. impl fmt::Display for CurrencyUnit {
  470. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  471. let s = match self {
  472. CurrencyUnit::Sat => "SAT",
  473. CurrencyUnit::Msat => "MSAT",
  474. CurrencyUnit::Usd => "USD",
  475. CurrencyUnit::Eur => "EUR",
  476. CurrencyUnit::Auth => "AUTH",
  477. CurrencyUnit::Custom(unit) => unit,
  478. };
  479. if let Some(width) = f.width() {
  480. write!(f, "{:width$}", s.to_lowercase(), width = width)
  481. } else {
  482. write!(f, "{}", s.to_lowercase())
  483. }
  484. }
  485. }
  486. impl Serialize for CurrencyUnit {
  487. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  488. where
  489. S: serde::Serializer,
  490. {
  491. serializer.serialize_str(&self.to_string())
  492. }
  493. }
  494. impl<'de> Deserialize<'de> for CurrencyUnit {
  495. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  496. where
  497. D: Deserializer<'de>,
  498. {
  499. let currency: String = String::deserialize(deserializer)?;
  500. Self::from_str(&currency).map_err(|_| serde::de::Error::custom("Unsupported unit"))
  501. }
  502. }
  503. /// Payment Method
  504. #[non_exhaustive]
  505. #[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
  506. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  507. pub enum PaymentMethod {
  508. /// Bolt11 payment type
  509. #[default]
  510. Bolt11,
  511. /// Custom
  512. Custom(String),
  513. }
  514. impl FromStr for PaymentMethod {
  515. type Err = Error;
  516. fn from_str(value: &str) -> Result<Self, Self::Err> {
  517. match value.to_lowercase().as_str() {
  518. "bolt11" => Ok(Self::Bolt11),
  519. c => Ok(Self::Custom(c.to_string())),
  520. }
  521. }
  522. }
  523. impl fmt::Display for PaymentMethod {
  524. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  525. match self {
  526. PaymentMethod::Bolt11 => write!(f, "bolt11"),
  527. PaymentMethod::Custom(p) => write!(f, "{}", p),
  528. }
  529. }
  530. }
  531. impl Serialize for PaymentMethod {
  532. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  533. where
  534. S: serde::Serializer,
  535. {
  536. serializer.serialize_str(&self.to_string())
  537. }
  538. }
  539. impl<'de> Deserialize<'de> for PaymentMethod {
  540. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  541. where
  542. D: Deserializer<'de>,
  543. {
  544. let payment_method: String = String::deserialize(deserializer)?;
  545. Self::from_str(&payment_method).map_err(|_| de::Error::custom("Unsupported payment method"))
  546. }
  547. }
  548. /// PreMint
  549. #[cfg(feature = "wallet")]
  550. #[derive(Debug, Clone, PartialEq, Eq, Serialize)]
  551. pub struct PreMint {
  552. /// Blinded message
  553. pub blinded_message: BlindedMessage,
  554. /// Secret
  555. pub secret: Secret,
  556. /// R
  557. pub r: SecretKey,
  558. /// Amount
  559. pub amount: Amount,
  560. }
  561. #[cfg(feature = "wallet")]
  562. impl Ord for PreMint {
  563. fn cmp(&self, other: &Self) -> std::cmp::Ordering {
  564. self.amount.cmp(&other.amount)
  565. }
  566. }
  567. #[cfg(feature = "wallet")]
  568. impl PartialOrd for PreMint {
  569. fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
  570. Some(self.cmp(other))
  571. }
  572. }
  573. /// Premint Secrets
  574. #[cfg(feature = "wallet")]
  575. #[derive(Debug, Clone, PartialEq, Eq, Serialize)]
  576. pub struct PreMintSecrets {
  577. /// Secrets
  578. pub secrets: Vec<PreMint>,
  579. /// Keyset Id
  580. pub keyset_id: Id,
  581. }
  582. #[cfg(feature = "wallet")]
  583. impl PreMintSecrets {
  584. /// Create new [`PreMintSecrets`]
  585. pub fn new(keyset_id: Id) -> Self {
  586. Self {
  587. secrets: Vec::new(),
  588. keyset_id,
  589. }
  590. }
  591. /// Outputs for speceifed amount with random secret
  592. pub fn random(
  593. keyset_id: Id,
  594. amount: Amount,
  595. amount_split_target: &SplitTarget,
  596. ) -> Result<Self, Error> {
  597. let amount_split = amount.split_targeted(amount_split_target)?;
  598. let mut output = Vec::with_capacity(amount_split.len());
  599. for amount in amount_split {
  600. let secret = Secret::generate();
  601. let (blinded, r) = blind_message(&secret.to_bytes(), None)?;
  602. let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
  603. output.push(PreMint {
  604. secret,
  605. blinded_message,
  606. r,
  607. amount,
  608. });
  609. }
  610. Ok(PreMintSecrets {
  611. secrets: output,
  612. keyset_id,
  613. })
  614. }
  615. /// Outputs from pre defined secrets
  616. pub fn from_secrets(
  617. keyset_id: Id,
  618. amounts: Vec<Amount>,
  619. secrets: Vec<Secret>,
  620. ) -> Result<Self, Error> {
  621. let mut output = Vec::with_capacity(secrets.len());
  622. for (secret, amount) in secrets.into_iter().zip(amounts) {
  623. let (blinded, r) = blind_message(&secret.to_bytes(), None)?;
  624. let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
  625. output.push(PreMint {
  626. secret,
  627. blinded_message,
  628. r,
  629. amount,
  630. });
  631. }
  632. Ok(PreMintSecrets {
  633. secrets: output,
  634. keyset_id,
  635. })
  636. }
  637. /// Blank Outputs used for NUT-08 change
  638. pub fn blank(keyset_id: Id, fee_reserve: Amount) -> Result<Self, Error> {
  639. let count = ((u64::from(fee_reserve) as f64).log2().ceil() as u64).max(1);
  640. let mut output = Vec::with_capacity(count as usize);
  641. for _i in 0..count {
  642. let secret = Secret::generate();
  643. let (blinded, r) = blind_message(&secret.to_bytes(), None)?;
  644. let blinded_message = BlindedMessage::new(Amount::ZERO, keyset_id, blinded);
  645. output.push(PreMint {
  646. secret,
  647. blinded_message,
  648. r,
  649. amount: Amount::ZERO,
  650. })
  651. }
  652. Ok(PreMintSecrets {
  653. secrets: output,
  654. keyset_id,
  655. })
  656. }
  657. /// Outputs with specific spending conditions
  658. pub fn with_conditions(
  659. keyset_id: Id,
  660. amount: Amount,
  661. amount_split_target: &SplitTarget,
  662. conditions: &SpendingConditions,
  663. ) -> Result<Self, Error> {
  664. let amount_split = amount.split_targeted(amount_split_target)?;
  665. let mut output = Vec::with_capacity(amount_split.len());
  666. for amount in amount_split {
  667. let secret: nut10::Secret = conditions.clone().into();
  668. let secret: Secret = secret.try_into()?;
  669. let (blinded, r) = blind_message(&secret.to_bytes(), None)?;
  670. let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
  671. output.push(PreMint {
  672. secret,
  673. blinded_message,
  674. r,
  675. amount,
  676. });
  677. }
  678. Ok(PreMintSecrets {
  679. secrets: output,
  680. keyset_id,
  681. })
  682. }
  683. /// Iterate over secrets
  684. #[inline]
  685. pub fn iter(&self) -> impl Iterator<Item = &PreMint> {
  686. self.secrets.iter()
  687. }
  688. /// Length of secrets
  689. #[inline]
  690. pub fn len(&self) -> usize {
  691. self.secrets.len()
  692. }
  693. /// If secrets is empty
  694. #[inline]
  695. pub fn is_empty(&self) -> bool {
  696. self.secrets.is_empty()
  697. }
  698. /// Totoal amount of secrets
  699. pub fn total_amount(&self) -> Result<Amount, Error> {
  700. Ok(Amount::try_sum(
  701. self.secrets.iter().map(|PreMint { amount, .. }| *amount),
  702. )?)
  703. }
  704. /// [`BlindedMessage`]s from [`PreMintSecrets`]
  705. #[inline]
  706. pub fn blinded_messages(&self) -> Vec<BlindedMessage> {
  707. self.iter().map(|pm| pm.blinded_message.clone()).collect()
  708. }
  709. /// [`Secret`]s from [`PreMintSecrets`]
  710. #[inline]
  711. pub fn secrets(&self) -> Vec<Secret> {
  712. self.iter().map(|pm| pm.secret.clone()).collect()
  713. }
  714. /// Blinding factor from [`PreMintSecrets`]
  715. #[inline]
  716. pub fn rs(&self) -> Vec<SecretKey> {
  717. self.iter().map(|pm| pm.r.clone()).collect()
  718. }
  719. /// Amounts from [`PreMintSecrets`]
  720. #[inline]
  721. pub fn amounts(&self) -> Vec<Amount> {
  722. self.iter().map(|pm| pm.amount).collect()
  723. }
  724. /// Combine [`PreMintSecrets`]
  725. #[inline]
  726. pub fn combine(&mut self, mut other: Self) {
  727. self.secrets.append(&mut other.secrets)
  728. }
  729. /// Sort [`PreMintSecrets`] by [`Amount`]
  730. #[inline]
  731. pub fn sort_secrets(&mut self) {
  732. self.secrets.sort();
  733. }
  734. }
  735. // Implement Iterator for PreMintSecrets
  736. #[cfg(feature = "wallet")]
  737. impl Iterator for PreMintSecrets {
  738. type Item = PreMint;
  739. fn next(&mut self) -> Option<Self::Item> {
  740. // Use the iterator of the vector
  741. self.secrets.pop()
  742. }
  743. }
  744. #[cfg(feature = "wallet")]
  745. impl Ord for PreMintSecrets {
  746. fn cmp(&self, other: &Self) -> Ordering {
  747. self.secrets.cmp(&other.secrets)
  748. }
  749. }
  750. #[cfg(feature = "wallet")]
  751. impl PartialOrd for PreMintSecrets {
  752. fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  753. Some(self.cmp(other))
  754. }
  755. }
  756. #[cfg(test)]
  757. mod tests {
  758. use std::str::FromStr;
  759. use super::*;
  760. #[test]
  761. fn test_proof_serialize() {
  762. let proof = "[{\"id\":\"009a1f293253e41e\",\"amount\":2,\"secret\":\"407915bc212be61a77e3e6d2aeb4c727980bda51cd06a6afc29e2861768a7837\",\"C\":\"02bc9097997d81afb2cc7346b5e4345a9346bd2a506eb7958598a72f0cf85163ea\"},{\"id\":\"009a1f293253e41e\",\"amount\":8,\"secret\":\"fe15109314e61d7756b0f8ee0f23a624acaa3f4e042f61433c728c7057b931be\",\"C\":\"029e8e5050b890a7d6c0968db16bc1d5d5fa040ea1de284f6ec69d61299f671059\"}]";
  763. let proof: Proofs = serde_json::from_str(proof).unwrap();
  764. assert_eq!(
  765. proof[0].clone().keyset_id,
  766. Id::from_str("009a1f293253e41e").unwrap()
  767. );
  768. assert_eq!(proof.len(), 2);
  769. }
  770. #[test]
  771. #[cfg(feature = "wallet")]
  772. fn test_blank_blinded_messages() {
  773. let b = PreMintSecrets::blank(
  774. Id::from_str("009a1f293253e41e").unwrap(),
  775. Amount::from(1000),
  776. )
  777. .unwrap();
  778. assert_eq!(b.len(), 10);
  779. let b = PreMintSecrets::blank(Id::from_str("009a1f293253e41e").unwrap(), Amount::from(1))
  780. .unwrap();
  781. assert_eq!(b.len(), 1);
  782. }
  783. }