mod.rs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. //! NUT-11: Pay to Public Key (P2PK)
  2. //!
  3. //! <https://github.com/cashubtc/nuts/blob/main/11.md>
  4. use std::collections::{HashMap, HashSet};
  5. use std::str::FromStr;
  6. use std::{fmt, vec};
  7. use bitcoin::hashes::sha256::Hash as Sha256Hash;
  8. use bitcoin::hashes::Hash;
  9. use bitcoin::secp256k1::schnorr::Signature;
  10. use serde::de::Error as DeserializerError;
  11. use serde::ser::SerializeSeq;
  12. use serde::{Deserialize, Deserializer, Serialize, Serializer};
  13. use thiserror::Error;
  14. use super::nut00::Witness;
  15. use super::nut01::PublicKey;
  16. use super::{Kind, Nut10Secret, Proof, Proofs, SecretKey};
  17. use crate::ensure_cdk;
  18. use crate::nuts::nut00::BlindedMessage;
  19. use crate::secret::Secret;
  20. use crate::util::{hex, unix_time};
  21. pub mod serde_p2pk_witness;
  22. /// Nut11 Error
  23. #[derive(Debug, Error)]
  24. pub enum Error {
  25. /// Incorrect secret kind
  26. #[error("Secret is not a p2pk secret")]
  27. IncorrectSecretKind,
  28. /// Incorrect secret kind
  29. #[error("Witness is not a p2pk witness")]
  30. IncorrectWitnessKind,
  31. /// P2PK locktime has already passed
  32. #[error("Locktime in past")]
  33. LocktimeInPast,
  34. /// Witness signature is not valid
  35. #[error("Invalid signature")]
  36. InvalidSignature,
  37. /// Unknown tag in P2PK secret
  38. #[error("Unknown tag P2PK secret")]
  39. UnknownTag,
  40. /// Unknown Sigflag
  41. #[error("Unknown sigflag")]
  42. UnknownSigFlag,
  43. /// P2PK Spend conditions not meet
  44. #[error("P2PK spend conditions are not met")]
  45. SpendConditionsNotMet,
  46. /// Pubkey must be in data field of P2PK
  47. #[error("P2PK required in secret data")]
  48. P2PKPubkeyRequired,
  49. /// Unknown Kind
  50. #[error("Kind not found")]
  51. KindNotFound,
  52. /// HTLC hash invalid
  53. #[error("Invalid hash")]
  54. InvalidHash,
  55. /// Witness Signatures not provided
  56. #[error("Witness signatures not provided")]
  57. SignaturesNotProvided,
  58. /// Duplicate signature from same pubkey
  59. #[error("Duplicate signature from the same pubkey detected")]
  60. DuplicateSignature,
  61. /// Parse Url Error
  62. #[error(transparent)]
  63. UrlParseError(#[from] url::ParseError),
  64. /// Parse int error
  65. #[error(transparent)]
  66. ParseInt(#[from] std::num::ParseIntError),
  67. /// From hex error
  68. #[error(transparent)]
  69. HexError(#[from] hex::Error),
  70. /// Serde Json error
  71. #[error(transparent)]
  72. SerdeJsonError(#[from] serde_json::Error),
  73. /// Secp256k1 error
  74. #[error(transparent)]
  75. Secp256k1(#[from] bitcoin::secp256k1::Error),
  76. /// NUT01 Error
  77. #[error(transparent)]
  78. NUT01(#[from] crate::nuts::nut01::Error),
  79. /// Secret error
  80. #[error(transparent)]
  81. Secret(#[from] crate::secret::Error),
  82. }
  83. /// P2Pk Witness
  84. #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  85. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  86. pub struct P2PKWitness {
  87. /// Signatures
  88. pub signatures: Vec<String>,
  89. }
  90. impl P2PKWitness {
  91. #[inline]
  92. /// Check id Witness is empty
  93. pub fn is_empty(&self) -> bool {
  94. self.signatures.is_empty()
  95. }
  96. }
  97. impl Proof {
  98. /// Sign [Proof]
  99. pub fn sign_p2pk(&mut self, secret_key: SecretKey) -> Result<(), Error> {
  100. let msg: Vec<u8> = self.secret.to_bytes();
  101. let signature: Signature = secret_key.sign(&msg)?;
  102. let signatures = vec![signature.to_string()];
  103. match self.witness.as_mut() {
  104. Some(witness) => {
  105. witness.add_signatures(signatures);
  106. }
  107. None => {
  108. let mut p2pk_witness = Witness::P2PKWitness(P2PKWitness::default());
  109. p2pk_witness.add_signatures(signatures);
  110. self.witness = Some(p2pk_witness);
  111. }
  112. };
  113. Ok(())
  114. }
  115. /// Verify P2PK signature on [Proof]
  116. pub fn verify_p2pk(&self) -> Result<(), Error> {
  117. let secret: Nut10Secret = self.secret.clone().try_into()?;
  118. let spending_conditions: Conditions =
  119. secret.secret_data.tags.unwrap_or_default().try_into()?;
  120. let msg: &[u8] = self.secret.as_bytes();
  121. let mut verified_pubkeys = HashSet::new();
  122. let witness_signatures = match &self.witness {
  123. Some(witness) => witness.signatures(),
  124. None => None,
  125. };
  126. let witness_signatures = witness_signatures.ok_or(Error::SignaturesNotProvided)?;
  127. let mut pubkeys = spending_conditions.pubkeys.clone().unwrap_or_default();
  128. if secret.kind.eq(&Kind::P2PK) {
  129. pubkeys.push(PublicKey::from_str(&secret.secret_data.data)?);
  130. }
  131. for signature in witness_signatures.iter() {
  132. for v in &pubkeys {
  133. let sig = Signature::from_str(signature)?;
  134. if v.verify(msg, &sig).is_ok() {
  135. // If the pubkey is already verified, return a duplicate signature error
  136. if !verified_pubkeys.insert(*v) {
  137. return Err(Error::DuplicateSignature);
  138. }
  139. } else {
  140. tracing::debug!(
  141. "Could not verify signature: {sig} on message: {}",
  142. self.secret.to_string()
  143. )
  144. }
  145. }
  146. }
  147. let valid_sigs = verified_pubkeys.len() as u64;
  148. if valid_sigs >= spending_conditions.num_sigs.unwrap_or(1) {
  149. return Ok(());
  150. }
  151. if let (Some(locktime), Some(refund_keys)) = (
  152. spending_conditions.locktime,
  153. spending_conditions.refund_keys,
  154. ) {
  155. // If lock time has passed check if refund witness signature is valid
  156. if locktime.lt(&unix_time()) {
  157. for s in witness_signatures.iter() {
  158. for v in &refund_keys {
  159. let sig = Signature::from_str(s).map_err(|_| Error::InvalidSignature)?;
  160. // As long as there is one valid refund signature it can be spent
  161. if v.verify(msg, &sig).is_ok() {
  162. return Ok(());
  163. }
  164. }
  165. }
  166. }
  167. }
  168. Err(Error::SpendConditionsNotMet)
  169. }
  170. }
  171. /// Returns count of valid signatures (each public key is only counted once)
  172. /// Returns error if the same pubkey has multiple valid signatures
  173. pub fn valid_signatures(
  174. msg: &[u8],
  175. pubkeys: &[PublicKey],
  176. signatures: &[Signature],
  177. ) -> Result<u64, Error> {
  178. let mut verified_pubkeys = HashSet::new();
  179. for pubkey in pubkeys {
  180. for signature in signatures {
  181. if pubkey.verify(msg, signature).is_ok() {
  182. // If the pubkey is already verified, return a duplicate signature error
  183. if !verified_pubkeys.insert(*pubkey) {
  184. return Err(Error::DuplicateSignature);
  185. }
  186. }
  187. }
  188. }
  189. Ok(verified_pubkeys.len() as u64)
  190. }
  191. impl BlindedMessage {
  192. /// Sign [BlindedMessage]
  193. pub fn sign_p2pk(&mut self, secret_key: SecretKey) -> Result<(), Error> {
  194. let msg: [u8; 33] = self.blinded_secret.to_bytes();
  195. let signature: Signature = secret_key.sign(&msg)?;
  196. let signatures = vec![signature.to_string()];
  197. match self.witness.as_mut() {
  198. Some(witness) => {
  199. witness.add_signatures(signatures);
  200. }
  201. None => {
  202. let mut p2pk_witness = Witness::P2PKWitness(P2PKWitness::default());
  203. p2pk_witness.add_signatures(signatures);
  204. self.witness = Some(p2pk_witness);
  205. }
  206. };
  207. Ok(())
  208. }
  209. /// Verify P2PK conditions on [BlindedMessage]
  210. pub fn verify_p2pk(&self, pubkeys: &Vec<PublicKey>, required_sigs: u64) -> Result<(), Error> {
  211. let mut verified_pubkeys = HashSet::new();
  212. if let Some(witness) = &self.witness {
  213. for signature in witness
  214. .signatures()
  215. .ok_or(Error::SignaturesNotProvided)?
  216. .iter()
  217. {
  218. for v in pubkeys {
  219. let msg = &self.blinded_secret.to_bytes();
  220. let sig = Signature::from_str(signature)?;
  221. if v.verify(msg, &sig).is_ok() {
  222. // If the pubkey is already verified, return a duplicate signature error
  223. if !verified_pubkeys.insert(*v) {
  224. return Err(Error::DuplicateSignature);
  225. }
  226. } else {
  227. tracing::debug!(
  228. "Could not verify signature: {sig} on message: {}",
  229. self.blinded_secret
  230. )
  231. }
  232. }
  233. }
  234. }
  235. let valid_sigs = verified_pubkeys.len() as u64;
  236. if valid_sigs.ge(&required_sigs) {
  237. Ok(())
  238. } else {
  239. Err(Error::SpendConditionsNotMet)
  240. }
  241. }
  242. }
  243. /// Spending Conditions
  244. ///
  245. /// Defined in [NUT10](https://github.com/cashubtc/nuts/blob/main/10.md)
  246. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  247. pub enum SpendingConditions {
  248. /// NUT11 Spending conditions
  249. ///
  250. /// Defined in [NUT11](https://github.com/cashubtc/nuts/blob/main/11.md)
  251. P2PKConditions {
  252. /// The public key of the recipient of the locked ecash
  253. data: PublicKey,
  254. /// Additional Optional Spending [`Conditions`]
  255. conditions: Option<Conditions>,
  256. },
  257. /// NUT14 Spending conditions
  258. ///
  259. /// Dedined in [NUT14](https://github.com/cashubtc/nuts/blob/main/14.md)
  260. HTLCConditions {
  261. /// Hash Lock of ecash
  262. data: Sha256Hash,
  263. /// Additional Optional Spending [`Conditions`]
  264. conditions: Option<Conditions>,
  265. },
  266. }
  267. impl SpendingConditions {
  268. /// New HTLC [SpendingConditions]
  269. pub fn new_htlc(preimage: String, conditions: Option<Conditions>) -> Result<Self, Error> {
  270. let htlc = Sha256Hash::hash(&hex::decode(preimage)?);
  271. Ok(Self::HTLCConditions {
  272. data: htlc,
  273. conditions,
  274. })
  275. }
  276. /// New P2PK [SpendingConditions]
  277. pub fn new_p2pk(pubkey: PublicKey, conditions: Option<Conditions>) -> Self {
  278. Self::P2PKConditions {
  279. data: pubkey,
  280. conditions,
  281. }
  282. }
  283. /// Kind of [SpendingConditions]
  284. pub fn kind(&self) -> Kind {
  285. match self {
  286. Self::P2PKConditions { .. } => Kind::P2PK,
  287. Self::HTLCConditions { .. } => Kind::HTLC,
  288. }
  289. }
  290. /// Number if signatures required to unlock
  291. pub fn num_sigs(&self) -> Option<u64> {
  292. match self {
  293. Self::P2PKConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.num_sigs),
  294. Self::HTLCConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.num_sigs),
  295. }
  296. }
  297. /// Public keys of locked [`Proof`]
  298. pub fn pubkeys(&self) -> Option<Vec<PublicKey>> {
  299. match self {
  300. Self::P2PKConditions { data, conditions } => {
  301. let mut pubkeys = vec![*data];
  302. if let Some(conditions) = conditions {
  303. pubkeys.extend(conditions.pubkeys.clone().unwrap_or_default());
  304. }
  305. Some(pubkeys)
  306. }
  307. Self::HTLCConditions { conditions, .. } => conditions.clone().and_then(|c| c.pubkeys),
  308. }
  309. }
  310. /// Locktime of Spending Conditions
  311. pub fn locktime(&self) -> Option<u64> {
  312. match self {
  313. Self::P2PKConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.locktime),
  314. Self::HTLCConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.locktime),
  315. }
  316. }
  317. /// Refund keys
  318. pub fn refund_keys(&self) -> Option<Vec<PublicKey>> {
  319. match self {
  320. Self::P2PKConditions { conditions, .. } => {
  321. conditions.clone().and_then(|c| c.refund_keys)
  322. }
  323. Self::HTLCConditions { conditions, .. } => {
  324. conditions.clone().and_then(|c| c.refund_keys)
  325. }
  326. }
  327. }
  328. }
  329. impl TryFrom<&Secret> for SpendingConditions {
  330. type Error = Error;
  331. fn try_from(secret: &Secret) -> Result<SpendingConditions, Error> {
  332. let nut10_secret: Nut10Secret = secret.try_into()?;
  333. nut10_secret.try_into()
  334. }
  335. }
  336. impl TryFrom<Nut10Secret> for SpendingConditions {
  337. type Error = Error;
  338. fn try_from(secret: Nut10Secret) -> Result<SpendingConditions, Error> {
  339. match secret.kind {
  340. Kind::P2PK => Ok(SpendingConditions::P2PKConditions {
  341. data: PublicKey::from_str(&secret.secret_data.data)?,
  342. conditions: secret.secret_data.tags.and_then(|t| t.try_into().ok()),
  343. }),
  344. Kind::HTLC => Ok(Self::HTLCConditions {
  345. data: Sha256Hash::from_str(&secret.secret_data.data)
  346. .map_err(|_| Error::InvalidHash)?,
  347. conditions: secret.secret_data.tags.and_then(|t| t.try_into().ok()),
  348. }),
  349. }
  350. }
  351. }
  352. impl From<SpendingConditions> for super::nut10::Secret {
  353. fn from(conditions: SpendingConditions) -> super::nut10::Secret {
  354. match conditions {
  355. SpendingConditions::P2PKConditions { data, conditions } => {
  356. super::nut10::Secret::new(Kind::P2PK, data.to_hex(), conditions)
  357. }
  358. SpendingConditions::HTLCConditions { data, conditions } => {
  359. super::nut10::Secret::new(Kind::HTLC, data.to_string(), conditions)
  360. }
  361. }
  362. }
  363. }
  364. /// P2PK and HTLC spending conditions
  365. #[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
  366. pub struct Conditions {
  367. /// Unix locktime after which refund keys can be used
  368. #[serde(skip_serializing_if = "Option::is_none")]
  369. pub locktime: Option<u64>,
  370. /// Additional Public keys
  371. #[serde(skip_serializing_if = "Option::is_none")]
  372. pub pubkeys: Option<Vec<PublicKey>>,
  373. /// Refund keys
  374. #[serde(skip_serializing_if = "Option::is_none")]
  375. pub refund_keys: Option<Vec<PublicKey>>,
  376. /// Numbedr of signatures required
  377. ///
  378. /// Default is 1
  379. #[serde(skip_serializing_if = "Option::is_none")]
  380. pub num_sigs: Option<u64>,
  381. /// Signature flag
  382. ///
  383. /// Default [`SigFlag::SigInputs`]
  384. pub sig_flag: SigFlag,
  385. }
  386. impl Conditions {
  387. /// Create new Spending [`Conditions`]
  388. pub fn new(
  389. locktime: Option<u64>,
  390. pubkeys: Option<Vec<PublicKey>>,
  391. refund_keys: Option<Vec<PublicKey>>,
  392. num_sigs: Option<u64>,
  393. sig_flag: Option<SigFlag>,
  394. ) -> Result<Self, Error> {
  395. if let Some(locktime) = locktime {
  396. ensure_cdk!(locktime.ge(&unix_time()), Error::LocktimeInPast);
  397. }
  398. Ok(Self {
  399. locktime,
  400. pubkeys,
  401. refund_keys,
  402. num_sigs,
  403. sig_flag: sig_flag.unwrap_or_default(),
  404. })
  405. }
  406. }
  407. impl From<Conditions> for Vec<Vec<String>> {
  408. fn from(conditions: Conditions) -> Vec<Vec<String>> {
  409. let Conditions {
  410. locktime,
  411. pubkeys,
  412. refund_keys,
  413. num_sigs,
  414. sig_flag,
  415. } = conditions;
  416. let mut tags = Vec::new();
  417. if let Some(pubkeys) = pubkeys {
  418. tags.push(Tag::PubKeys(pubkeys.into_iter().collect()).as_vec());
  419. }
  420. if let Some(locktime) = locktime {
  421. tags.push(Tag::LockTime(locktime).as_vec());
  422. }
  423. if let Some(num_sigs) = num_sigs {
  424. tags.push(Tag::NSigs(num_sigs).as_vec());
  425. }
  426. if let Some(refund_keys) = refund_keys {
  427. tags.push(Tag::Refund(refund_keys).as_vec())
  428. }
  429. tags.push(Tag::SigFlag(sig_flag).as_vec());
  430. tags
  431. }
  432. }
  433. impl TryFrom<Vec<Vec<String>>> for Conditions {
  434. type Error = Error;
  435. fn try_from(tags: Vec<Vec<String>>) -> Result<Conditions, Self::Error> {
  436. let tags: HashMap<TagKind, Tag> = tags
  437. .into_iter()
  438. .map(|t| Tag::try_from(t).unwrap())
  439. .map(|t| (t.kind(), t))
  440. .collect();
  441. let pubkeys = match tags.get(&TagKind::Pubkeys) {
  442. Some(Tag::PubKeys(pubkeys)) => Some(pubkeys.clone()),
  443. _ => None,
  444. };
  445. let locktime = if let Some(tag) = tags.get(&TagKind::Locktime) {
  446. match tag {
  447. Tag::LockTime(locktime) => Some(*locktime),
  448. _ => None,
  449. }
  450. } else {
  451. None
  452. };
  453. let refund_keys = if let Some(tag) = tags.get(&TagKind::Refund) {
  454. match tag {
  455. Tag::Refund(keys) => Some(keys.clone()),
  456. _ => None,
  457. }
  458. } else {
  459. None
  460. };
  461. let sig_flag = if let Some(tag) = tags.get(&TagKind::SigFlag) {
  462. match tag {
  463. Tag::SigFlag(sigflag) => *sigflag,
  464. _ => SigFlag::SigInputs,
  465. }
  466. } else {
  467. SigFlag::SigInputs
  468. };
  469. let num_sigs = if let Some(tag) = tags.get(&TagKind::NSigs) {
  470. match tag {
  471. Tag::NSigs(num_sigs) => Some(*num_sigs),
  472. _ => None,
  473. }
  474. } else {
  475. None
  476. };
  477. Ok(Conditions {
  478. locktime,
  479. pubkeys,
  480. refund_keys,
  481. num_sigs,
  482. sig_flag,
  483. })
  484. }
  485. }
  486. /// P2PK and HTLC Spending condition tags
  487. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
  488. #[serde(rename_all = "lowercase")]
  489. pub enum TagKind {
  490. /// Signature flag
  491. SigFlag,
  492. /// Number signatures required
  493. #[serde(rename = "n_sigs")]
  494. NSigs,
  495. /// Locktime
  496. Locktime,
  497. /// Refund
  498. Refund,
  499. /// Pubkey
  500. Pubkeys,
  501. /// Custom tag kind
  502. Custom(String),
  503. }
  504. impl fmt::Display for TagKind {
  505. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  506. match self {
  507. Self::SigFlag => write!(f, "sigflag"),
  508. Self::NSigs => write!(f, "n_sigs"),
  509. Self::Locktime => write!(f, "locktime"),
  510. Self::Refund => write!(f, "refund"),
  511. Self::Pubkeys => write!(f, "pubkeys"),
  512. Self::Custom(kind) => write!(f, "{}", kind),
  513. }
  514. }
  515. }
  516. impl<S> From<S> for TagKind
  517. where
  518. S: AsRef<str>,
  519. {
  520. fn from(tag: S) -> Self {
  521. match tag.as_ref() {
  522. "sigflag" => Self::SigFlag,
  523. "n_sigs" => Self::NSigs,
  524. "locktime" => Self::Locktime,
  525. "refund" => Self::Refund,
  526. "pubkeys" => Self::Pubkeys,
  527. t => Self::Custom(t.to_owned()),
  528. }
  529. }
  530. }
  531. /// Signature flag
  532. ///
  533. /// Defined in [NUT11](https://github.com/cashubtc/nuts/blob/main/11.md)
  534. #[derive(
  535. Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash,
  536. )]
  537. pub enum SigFlag {
  538. #[default]
  539. /// Requires valid signatures on all inputs.
  540. /// It is the default signature flag and will be applied even if the
  541. /// `sigflag` tag is absent.
  542. SigInputs,
  543. /// Requires valid signatures on all inputs and on all outputs.
  544. SigAll,
  545. }
  546. impl fmt::Display for SigFlag {
  547. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  548. match self {
  549. Self::SigAll => write!(f, "SIG_ALL"),
  550. Self::SigInputs => write!(f, "SIG_INPUTS"),
  551. }
  552. }
  553. }
  554. impl FromStr for SigFlag {
  555. type Err = Error;
  556. fn from_str(tag: &str) -> Result<Self, Self::Err> {
  557. match tag {
  558. "SIG_ALL" => Ok(Self::SigAll),
  559. "SIG_INPUTS" => Ok(Self::SigInputs),
  560. _ => Err(Error::UnknownSigFlag),
  561. }
  562. }
  563. }
  564. /// Get the signature flag that should be enforced for a set of proofs and the
  565. /// public keys that signatures are valid for
  566. pub fn enforce_sig_flag(proofs: Proofs) -> EnforceSigFlag {
  567. let mut sig_flag = SigFlag::SigInputs;
  568. let mut pubkeys = HashSet::new();
  569. let mut sigs_required = 1;
  570. for proof in proofs {
  571. if let Ok(secret) = Nut10Secret::try_from(proof.secret) {
  572. if secret.kind.eq(&Kind::P2PK) {
  573. if let Ok(verifying_key) = PublicKey::from_str(&secret.secret_data.data) {
  574. pubkeys.insert(verifying_key);
  575. }
  576. }
  577. if let Some(tags) = secret.secret_data.tags {
  578. if let Ok(conditions) = Conditions::try_from(tags) {
  579. if conditions.sig_flag.eq(&SigFlag::SigAll) {
  580. sig_flag = SigFlag::SigAll;
  581. }
  582. if let Some(sigs) = conditions.num_sigs {
  583. if sigs > sigs_required {
  584. sigs_required = sigs;
  585. }
  586. }
  587. if let Some(pubs) = conditions.pubkeys {
  588. pubkeys.extend(pubs);
  589. }
  590. }
  591. }
  592. }
  593. }
  594. EnforceSigFlag {
  595. sig_flag,
  596. pubkeys,
  597. sigs_required,
  598. }
  599. }
  600. /// Enforce Sigflag info
  601. #[derive(Debug, Clone, PartialEq, Eq)]
  602. pub struct EnforceSigFlag {
  603. /// Sigflag required for proofs
  604. pub sig_flag: SigFlag,
  605. /// Pubkeys that can sign for proofs
  606. pub pubkeys: HashSet<PublicKey>,
  607. /// Number of sigs required for proofs
  608. pub sigs_required: u64,
  609. }
  610. /// Tag
  611. #[derive(Debug, Clone, Hash, PartialEq, Eq)]
  612. pub enum Tag {
  613. /// Sigflag [`Tag`]
  614. SigFlag(SigFlag),
  615. /// Number of Sigs [`Tag`]
  616. NSigs(u64),
  617. /// Locktime [`Tag`]
  618. LockTime(u64),
  619. /// Refund [`Tag`]
  620. Refund(Vec<PublicKey>),
  621. /// Pubkeys [`Tag`]
  622. PubKeys(Vec<PublicKey>),
  623. }
  624. impl Tag {
  625. /// Get [`Tag`] Kind
  626. pub fn kind(&self) -> TagKind {
  627. match self {
  628. Self::SigFlag(_) => TagKind::SigFlag,
  629. Self::NSigs(_) => TagKind::NSigs,
  630. Self::LockTime(_) => TagKind::Locktime,
  631. Self::Refund(_) => TagKind::Refund,
  632. Self::PubKeys(_) => TagKind::Pubkeys,
  633. }
  634. }
  635. /// Get [`Tag`] as string vector
  636. pub fn as_vec(&self) -> Vec<String> {
  637. self.clone().into()
  638. }
  639. }
  640. impl<S> TryFrom<Vec<S>> for Tag
  641. where
  642. S: AsRef<str>,
  643. {
  644. type Error = Error;
  645. fn try_from(tag: Vec<S>) -> Result<Self, Self::Error> {
  646. let tag_kind = tag.first().map(TagKind::from).ok_or(Error::KindNotFound)?;
  647. match tag_kind {
  648. TagKind::SigFlag => Ok(Tag::SigFlag(SigFlag::from_str(tag[1].as_ref())?)),
  649. TagKind::NSigs => Ok(Tag::NSigs(tag[1].as_ref().parse()?)),
  650. TagKind::Locktime => Ok(Tag::LockTime(tag[1].as_ref().parse()?)),
  651. TagKind::Refund => {
  652. let pubkeys = tag
  653. .iter()
  654. .skip(1)
  655. .map(|p| PublicKey::from_str(p.as_ref()))
  656. .collect::<Result<Vec<PublicKey>, _>>()?;
  657. Ok(Self::Refund(pubkeys))
  658. }
  659. TagKind::Pubkeys => {
  660. let pubkeys = tag
  661. .iter()
  662. .skip(1)
  663. .map(|p| PublicKey::from_str(p.as_ref()))
  664. .collect::<Result<Vec<PublicKey>, _>>()?;
  665. Ok(Self::PubKeys(pubkeys))
  666. }
  667. _ => Err(Error::UnknownTag),
  668. }
  669. }
  670. }
  671. impl From<Tag> for Vec<String> {
  672. fn from(data: Tag) -> Self {
  673. match data {
  674. Tag::SigFlag(sigflag) => vec![TagKind::SigFlag.to_string(), sigflag.to_string()],
  675. Tag::NSigs(num_sig) => vec![TagKind::NSigs.to_string(), num_sig.to_string()],
  676. Tag::LockTime(locktime) => vec![TagKind::Locktime.to_string(), locktime.to_string()],
  677. Tag::PubKeys(pubkeys) => {
  678. let mut tag = vec![TagKind::Pubkeys.to_string()];
  679. for pubkey in pubkeys.into_iter() {
  680. tag.push(pubkey.to_string())
  681. }
  682. tag
  683. }
  684. Tag::Refund(pubkeys) => {
  685. let mut tag = vec![TagKind::Refund.to_string()];
  686. for pubkey in pubkeys {
  687. tag.push(pubkey.to_string())
  688. }
  689. tag
  690. }
  691. }
  692. }
  693. }
  694. impl Serialize for Tag {
  695. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  696. where
  697. S: Serializer,
  698. {
  699. let data: Vec<String> = self.as_vec();
  700. let mut seq = serializer.serialize_seq(Some(data.len()))?;
  701. for element in data.into_iter() {
  702. seq.serialize_element(&element)?;
  703. }
  704. seq.end()
  705. }
  706. }
  707. impl<'de> Deserialize<'de> for Tag {
  708. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  709. where
  710. D: Deserializer<'de>,
  711. {
  712. type Data = Vec<String>;
  713. let vec: Vec<String> = Data::deserialize(deserializer)?;
  714. Self::try_from(vec).map_err(DeserializerError::custom)
  715. }
  716. }
  717. #[cfg(test)]
  718. mod tests {
  719. use std::str::FromStr;
  720. use super::*;
  721. use crate::nuts::Id;
  722. use crate::secret::Secret;
  723. use crate::Amount;
  724. #[test]
  725. fn test_secret_ser() {
  726. let data = PublicKey::from_str(
  727. "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
  728. )
  729. .unwrap();
  730. let conditions = Conditions {
  731. locktime: Some(99999),
  732. pubkeys: Some(vec![
  733. PublicKey::from_str(
  734. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  735. )
  736. .unwrap(),
  737. PublicKey::from_str(
  738. "023192200a0cfd3867e48eb63b03ff599c7e46c8f4e41146b2d281173ca6c50c54",
  739. )
  740. .unwrap(),
  741. ]),
  742. refund_keys: Some(vec![PublicKey::from_str(
  743. "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
  744. )
  745. .unwrap()]),
  746. num_sigs: Some(2),
  747. sig_flag: SigFlag::SigAll,
  748. };
  749. let secret: Nut10Secret = Nut10Secret::new(Kind::P2PK, data.to_string(), Some(conditions));
  750. let secret_str = serde_json::to_string(&secret).unwrap();
  751. let secret_der: Nut10Secret = serde_json::from_str(&secret_str).unwrap();
  752. assert_eq!(secret_der, secret);
  753. }
  754. #[test]
  755. fn sign_proof() {
  756. let secret_key =
  757. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  758. .unwrap();
  759. let signing_key_two =
  760. SecretKey::from_str("0000000000000000000000000000000000000000000000000000000000000001")
  761. .unwrap();
  762. let signing_key_three =
  763. SecretKey::from_str("7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f")
  764. .unwrap();
  765. let v_key: PublicKey = secret_key.public_key();
  766. let v_key_two: PublicKey = signing_key_two.public_key();
  767. let v_key_three: PublicKey = signing_key_three.public_key();
  768. let conditions = Conditions {
  769. locktime: Some(21000000000),
  770. pubkeys: Some(vec![v_key_two, v_key_three]),
  771. refund_keys: Some(vec![v_key]),
  772. num_sigs: Some(2),
  773. sig_flag: SigFlag::SigInputs,
  774. };
  775. let secret: Secret = Nut10Secret::new(Kind::P2PK, v_key.to_string(), Some(conditions))
  776. .try_into()
  777. .unwrap();
  778. let mut proof = Proof {
  779. keyset_id: Id::from_str("009a1f293253e41e").unwrap(),
  780. amount: Amount::ZERO,
  781. secret,
  782. c: PublicKey::from_str(
  783. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  784. )
  785. .unwrap(),
  786. witness: Some(Witness::P2PKWitness(P2PKWitness { signatures: vec![] })),
  787. dleq: None,
  788. };
  789. proof.sign_p2pk(secret_key).unwrap();
  790. proof.sign_p2pk(signing_key_two).unwrap();
  791. assert!(proof.verify_p2pk().is_ok());
  792. }
  793. #[test]
  794. fn test_verify() {
  795. // Proof with a valid signature
  796. let json: &str = r#"{
  797. "amount":1,
  798. "secret":"[\"P2PK\",{\"nonce\":\"859d4935c4907062a6297cf4e663e2835d90d97ecdd510745d32f6816323a41f\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_INPUTS\"]]}]",
  799. "C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  800. "id":"009a1f293253e41e",
  801. "witness":"{\"signatures\":[\"60f3c9b766770b46caac1d27e1ae6b77c8866ebaeba0b9489fe6a15a837eaa6fcd6eaa825499c72ac342983983fd3ba3a8a41f56677cc99ffd73da68b59e1383\"]}"
  802. }"#;
  803. let valid_proof: Proof = serde_json::from_str(json).unwrap();
  804. valid_proof.verify_p2pk().unwrap();
  805. assert!(valid_proof.verify_p2pk().is_ok());
  806. // Proof with a signature that is in a different secret
  807. let invalid_proof = r#"{"amount":1,"secret":"[\"P2PK\",{\"nonce\":\"859d4935c4907062a6297cf4e663e2835d90d97ecdd510745d32f6816323a41f\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","id":"009a1f293253e41e","witness":"{\"signatures\":[\"3426df9730d365a9d18d79bed2f3e78e9172d7107c55306ac5ddd1b2d065893366cfa24ff3c874ebf1fc22360ba5888ddf6ff5dbcb9e5f2f5a1368f7afc64f15\"]}"}"#;
  808. let invalid_proof: Proof = serde_json::from_str(invalid_proof).unwrap();
  809. assert!(invalid_proof.verify_p2pk().is_err());
  810. }
  811. #[test]
  812. fn verify_multi_sig() {
  813. // Proof with 2 valid signatures to satifiy the condition
  814. let valid_proof = r#"{"amount":0,"secret":"[\"P2PK\",{\"nonce\":\"0ed3fcb22c649dd7bbbdcca36e0c52d4f0187dd3b6a19efcc2bfbebb5f85b2a1\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"pubkeys\",\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"02142715675faf8da1ecc4d51e0b9e539fa0d52fdd96ed60dbe99adb15d6b05ad9\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","id":"009a1f293253e41e","witness":"{\"signatures\":[\"83564aca48c668f50d022a426ce0ed19d3a9bdcffeeaee0dc1e7ea7e98e9eff1840fcc821724f623468c94f72a8b0a7280fa9ef5a54a1b130ef3055217f467b3\",\"9a72ca2d4d5075be5b511ee48dbc5e45f259bcf4a4e8bf18587f433098a9cd61ff9737dc6e8022de57c76560214c4568377792d4c2c6432886cc7050487a1f22\"]}"}"#;
  815. let valid_proof: Proof = serde_json::from_str(valid_proof).unwrap();
  816. assert!(valid_proof.verify_p2pk().is_ok());
  817. // Proof with only one of the required signatures
  818. let invalid_proof = r#"{"amount":0,"secret":"[\"P2PK\",{\"nonce\":\"0ed3fcb22c649dd7bbbdcca36e0c52d4f0187dd3b6a19efcc2bfbebb5f85b2a1\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"pubkeys\",\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"02142715675faf8da1ecc4d51e0b9e539fa0d52fdd96ed60dbe99adb15d6b05ad9\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","id":"009a1f293253e41e","witness":"{\"signatures\":[\"83564aca48c668f50d022a426ce0ed19d3a9bdcffeeaee0dc1e7ea7e98e9eff1840fcc821724f623468c94f72a8b0a7280fa9ef5a54a1b130ef3055217f467b3\"]}"}"#;
  819. let invalid_proof: Proof = serde_json::from_str(invalid_proof).unwrap();
  820. // Verification should fail without the requires signatures
  821. assert!(invalid_proof.verify_p2pk().is_err());
  822. }
  823. #[test]
  824. fn verify_refund() {
  825. let valid_proof = r#"{"amount":1,"id":"009a1f293253e41e","secret":"[\"P2PK\",{\"nonce\":\"902685f492ef3bb2ca35a47ddbba484a3365d143b9776d453947dcbf1ddf9689\",\"data\":\"026f6a2b1d709dbca78124a9f30a742985f7eddd894e72f637f7085bf69b997b9a\",\"tags\":[[\"pubkeys\",\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"03142715675faf8da1ecc4d51e0b9e539fa0d52fdd96ed60dbe99adb15d6b05ad9\"],[\"locktime\",\"21\"],[\"n_sigs\",\"2\"],[\"refund\",\"026f6a2b1d709dbca78124a9f30a742985f7eddd894e72f637f7085bf69b997b9a\"],[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","witness":"{\"signatures\":[\"710507b4bc202355c91ea3c147c0d0189c75e179d995e566336afd759cb342bcad9a593345f559d9b9e108ac2c9b5bd9f0b4b6a295028a98606a0a2e95eb54f7\"]}"}"#;
  826. let valid_proof: Proof = serde_json::from_str(valid_proof).unwrap();
  827. assert!(valid_proof.verify_p2pk().is_ok());
  828. let invalid_proof = r#"{"amount":1,"id":"009a1f293253e41e","secret":"[\"P2PK\",{\"nonce\":\"64c46e5d30df27286166814b71b5d69801704f23a7ad626b05688fbdb48dcc98\",\"data\":\"026f6a2b1d709dbca78124a9f30a742985f7eddd894e72f637f7085bf69b997b9a\",\"tags\":[[\"pubkeys\",\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"03142715675faf8da1ecc4d51e0b9e539fa0d52fdd96ed60dbe99adb15d6b05ad9\"],[\"locktime\",\"21\"],[\"n_sigs\",\"2\"],[\"refund\",\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"],[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","witness":"{\"signatures\":[\"f661d3dc046d636d47cb3d06586da42c498f0300373d1c2a4f417a44252cdf3809bce207c8888f934dba0d2b1671f1b8622d526840f2d5883e571b462630c1ff\"]}"}"#;
  829. let invalid_proof: Proof = serde_json::from_str(invalid_proof).unwrap();
  830. assert!(invalid_proof.verify_p2pk().is_err());
  831. }
  832. #[test]
  833. fn test_duplicate_signatures_counting() {
  834. let proof: Proof = serde_json::from_str(
  835. r#"{"amount":1,"id":"009a1f293253e41e","secret":"[\"P2PK\",{\"nonce\":\"e434a9efbc5f65d144a620e368c9a6dc12c719d0ebc57e0c74f7341864dc449a\",\"data\":\"02a60c27104cf6023581e790970fc33994a320abe36e7ceed16771b0f8d76f0666\",\"tags\":[[\"pubkeys\",\"039c6a20a6ba354b7bb92eb9750716c1098063006362a1fa2afca7421f262d45c5\",\"0203eb2f7cd72a4f725d3327216365d2df18bb4bbc810522fd973c9af987e9b05b\"],[\"locktime\",\"1744876528\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","witness":"{\"signatures\":[\"3e9ff9e55c9eccb9e5aa0b6c62d54500b40d0eebadb06efcc8e76f3ce38e0923f956ec1bccb9080db96a17c1e98a1b857abfd1a56bb25670037cea3db1f73d81\",\"c5e29c38e60c4db720cf3f78e590358cf1291a06b9eadf77c1108ae84d533520c2707ffda224eb6a63fddaee9abd5ecf8f2cd263d2556950550e3061a5511f65\"]}"}"#,
  836. ).unwrap();
  837. assert!(proof.verify_p2pk().is_err());
  838. }
  839. }