mod.rs 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265
  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::{DeserializeOwned, 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::nut05::MeltRequest;
  17. use super::nut10::SpendingConditionVerification;
  18. use super::{Kind, Nut10Secret, Proof, Proofs, SecretKey};
  19. use crate::nuts::nut00::BlindedMessage;
  20. use crate::secret::Secret;
  21. use crate::util::{hex, unix_time};
  22. use crate::{ensure_cdk, SwapRequest};
  23. pub mod serde_p2pk_witness;
  24. /// Nut11 Error
  25. #[derive(Debug, Error)]
  26. pub enum Error {
  27. /// Incorrect secret kind
  28. #[error("Secret is not a p2pk secret")]
  29. IncorrectSecretKind,
  30. /// Incorrect secret kind
  31. #[error("Witness is not a p2pk witness")]
  32. IncorrectWitnessKind,
  33. /// P2PK locktime has already passed
  34. #[error("Locktime in past")]
  35. LocktimeInPast,
  36. /// Witness signature is not valid
  37. #[error("Invalid signature")]
  38. InvalidSignature,
  39. /// Unknown tag in P2PK secret
  40. #[error("Unknown tag P2PK secret")]
  41. UnknownTag,
  42. /// Unknown Sigflag
  43. #[error("Unknown sigflag")]
  44. UnknownSigFlag,
  45. /// P2PK Spend conditions not meet
  46. #[error("P2PK spend conditions are not met")]
  47. SpendConditionsNotMet,
  48. /// Pubkey must be in data field of P2PK
  49. #[error("P2PK required in secret data")]
  50. P2PKPubkeyRequired,
  51. /// Unknown Kind
  52. #[error("Kind not found")]
  53. KindNotFound,
  54. /// HTLC hash invalid
  55. #[error("Invalid hash")]
  56. InvalidHash,
  57. /// HTLC preimage too large
  58. #[error("Preimage exceeds maximum size of 32 bytes (64 hex characters)")]
  59. PreimageTooLarge,
  60. /// Witness Signatures not provided
  61. #[error("Witness signatures not provided")]
  62. SignaturesNotProvided,
  63. /// Duplicate signature from same pubkey
  64. #[error("Duplicate signature from the same pubkey detected")]
  65. DuplicateSignature,
  66. /// Preimage not supported in P2PK
  67. #[error("P2PK does not support preimage requirements")]
  68. PreimageNotSupportedInP2PK,
  69. /// SIG_ALL not supported in this context
  70. #[error("SIG_ALL proofs must be verified using a different method")]
  71. SigAllNotSupportedHere,
  72. /// Parse Url Error
  73. #[error(transparent)]
  74. UrlParseError(#[from] url::ParseError),
  75. /// Parse int error
  76. #[error(transparent)]
  77. ParseInt(#[from] std::num::ParseIntError),
  78. /// From hex error
  79. #[error(transparent)]
  80. HexError(#[from] hex::Error),
  81. /// Serde Json error
  82. #[error(transparent)]
  83. SerdeJsonError(#[from] serde_json::Error),
  84. /// Secp256k1 error
  85. #[error(transparent)]
  86. Secp256k1(#[from] bitcoin::secp256k1::Error),
  87. /// NUT01 Error
  88. #[error(transparent)]
  89. NUT01(#[from] crate::nuts::nut01::Error),
  90. /// Secret error
  91. #[error(transparent)]
  92. Secret(#[from] crate::secret::Error),
  93. }
  94. /// P2Pk Witness
  95. #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  96. #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
  97. pub struct P2PKWitness {
  98. /// Signatures
  99. pub signatures: Vec<String>,
  100. }
  101. impl P2PKWitness {
  102. #[inline]
  103. /// Check id Witness is empty
  104. pub fn is_empty(&self) -> bool {
  105. self.signatures.is_empty()
  106. }
  107. }
  108. impl Proof {
  109. /// Sign [Proof]
  110. pub fn sign_p2pk(&mut self, secret_key: SecretKey) -> Result<(), Error> {
  111. let msg: Vec<u8> = self.secret.to_bytes();
  112. let signature: Signature = secret_key.sign(&msg)?;
  113. let signatures = vec![signature.to_string()];
  114. match self.witness.as_mut() {
  115. Some(witness) => {
  116. witness.add_signatures(signatures);
  117. }
  118. None => {
  119. let mut p2pk_witness = Witness::P2PKWitness(P2PKWitness::default());
  120. p2pk_witness.add_signatures(signatures);
  121. self.witness = Some(p2pk_witness);
  122. }
  123. };
  124. Ok(())
  125. }
  126. /// Verify P2PK signature on [Proof]
  127. pub fn verify_p2pk(&self) -> Result<(), Error> {
  128. let secret: Nut10Secret = self.secret.clone().try_into()?;
  129. let spending_conditions: Conditions = secret
  130. .secret_data()
  131. .tags()
  132. .cloned()
  133. .unwrap_or_default()
  134. .try_into()?;
  135. if spending_conditions.sig_flag == SigFlag::SigAll {
  136. return Err(Error::SigAllNotSupportedHere);
  137. }
  138. if secret.kind() != Kind::P2PK {
  139. return Err(Error::IncorrectSecretKind);
  140. }
  141. // Based on the current time, we must identify the relevant keys
  142. let now = unix_time();
  143. let requirements = super::nut10::get_pubkeys_and_required_sigs(&secret, now)?;
  144. if requirements.preimage_needed {
  145. return Err(Error::PreimageNotSupportedInP2PK);
  146. }
  147. // Handle "anyone can spend" case (locktime passed with no refund keys)
  148. if requirements.required_sigs == 0 {
  149. return Ok(());
  150. }
  151. // Extract witness signatures
  152. let witness_signatures = match &self.witness {
  153. Some(witness) => witness.signatures(),
  154. None => None,
  155. };
  156. let witness_signatures = witness_signatures.ok_or(Error::SignaturesNotProvided)?;
  157. // Count valid signatures using relevant_pubkeys
  158. let msg: &[u8] = self.secret.as_bytes();
  159. let valid_sig_count = valid_signatures(
  160. msg,
  161. &requirements.pubkeys,
  162. &witness_signatures
  163. .iter()
  164. .map(|s| Signature::from_str(s))
  165. .collect::<Result<Vec<_>, _>>()?,
  166. )?;
  167. // Check if we have enough valid signatures
  168. if valid_sig_count >= requirements.required_sigs {
  169. Ok(())
  170. } else {
  171. Err(Error::SpendConditionsNotMet)
  172. }
  173. }
  174. }
  175. /// Returns count of valid signatures (each public key is only counted once)
  176. /// Returns error if the same pubkey has multiple valid signatures
  177. pub fn valid_signatures(
  178. msg: &[u8],
  179. pubkeys: &[PublicKey],
  180. signatures: &[Signature],
  181. ) -> Result<u64, Error> {
  182. let mut verified_pubkeys = HashSet::new();
  183. for pubkey in pubkeys {
  184. for signature in signatures {
  185. if pubkey.verify(msg, signature).is_ok() {
  186. // If the pubkey is already verified, return a duplicate signature error
  187. if !verified_pubkeys.insert(*pubkey) {
  188. return Err(Error::DuplicateSignature);
  189. }
  190. }
  191. }
  192. }
  193. Ok(verified_pubkeys.len() as u64)
  194. }
  195. impl BlindedMessage {
  196. /// Sign [BlindedMessage]
  197. pub fn sign_p2pk(&mut self, secret_key: SecretKey) -> Result<(), Error> {
  198. let msg: [u8; 33] = self.blinded_secret.to_bytes();
  199. let signature: Signature = secret_key.sign(&msg)?;
  200. let signatures = vec![signature.to_string()];
  201. match self.witness.as_mut() {
  202. Some(witness) => {
  203. witness.add_signatures(signatures);
  204. }
  205. None => {
  206. let mut p2pk_witness = Witness::P2PKWitness(P2PKWitness::default());
  207. p2pk_witness.add_signatures(signatures);
  208. self.witness = Some(p2pk_witness);
  209. }
  210. };
  211. Ok(())
  212. }
  213. /// Verify P2PK conditions on [BlindedMessage]
  214. pub fn verify_p2pk(&self, pubkeys: &Vec<PublicKey>, required_sigs: u64) -> Result<(), Error> {
  215. let mut verified_pubkeys = HashSet::new();
  216. if let Some(witness) = &self.witness {
  217. for signature in witness
  218. .signatures()
  219. .ok_or(Error::SignaturesNotProvided)?
  220. .iter()
  221. {
  222. for v in pubkeys {
  223. let msg = &self.blinded_secret.to_bytes();
  224. let sig = Signature::from_str(signature)?;
  225. if v.verify(msg, &sig).is_ok() {
  226. // If the pubkey is already verified, return a duplicate signature error
  227. if !verified_pubkeys.insert(*v) {
  228. return Err(Error::DuplicateSignature);
  229. }
  230. } else {
  231. tracing::debug!(
  232. "Could not verify signature: {sig} on message: {}",
  233. self.blinded_secret
  234. )
  235. }
  236. }
  237. }
  238. }
  239. let valid_sigs = verified_pubkeys.len() as u64;
  240. if valid_sigs.ge(&required_sigs) {
  241. Ok(())
  242. } else {
  243. Err(Error::SpendConditionsNotMet)
  244. }
  245. }
  246. }
  247. /// Spending Conditions
  248. ///
  249. /// Defined in [NUT10](https://github.com/cashubtc/nuts/blob/main/10.md)
  250. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  251. pub enum SpendingConditions {
  252. /// NUT11 Spending conditions
  253. ///
  254. /// Defined in [NUT11](https://github.com/cashubtc/nuts/blob/main/11.md)
  255. P2PKConditions {
  256. /// The public key of the recipient of the locked ecash
  257. data: PublicKey,
  258. /// Additional Optional Spending [`Conditions`]
  259. conditions: Option<Conditions>,
  260. },
  261. /// NUT14 Spending conditions
  262. ///
  263. /// Dedined in [NUT14](https://github.com/cashubtc/nuts/blob/main/14.md)
  264. HTLCConditions {
  265. /// Hash Lock of ecash
  266. data: Sha256Hash,
  267. /// Additional Optional Spending [`Conditions`]
  268. conditions: Option<Conditions>,
  269. },
  270. }
  271. impl SpendingConditions {
  272. /// New HTLC [SpendingConditions]
  273. pub fn new_htlc(preimage: String, conditions: Option<Conditions>) -> Result<Self, Error> {
  274. const MAX_PREIMAGE_BYTES: usize = 32;
  275. let preimage_bytes = hex::decode(preimage)?;
  276. if preimage_bytes.len() != MAX_PREIMAGE_BYTES {
  277. return Err(Error::PreimageTooLarge);
  278. }
  279. let htlc = Sha256Hash::hash(&preimage_bytes);
  280. Ok(Self::HTLCConditions {
  281. data: htlc,
  282. conditions,
  283. })
  284. }
  285. /// New HTLC [SpendingConditions] from a hash directly instead of preimage
  286. pub fn new_htlc_hash(hash: &str, conditions: Option<Conditions>) -> Result<Self, Error> {
  287. let hash = Sha256Hash::from_str(hash).map_err(|_| Error::InvalidHash)?;
  288. Ok(Self::HTLCConditions {
  289. data: hash,
  290. conditions,
  291. })
  292. }
  293. /// New P2PK [SpendingConditions]
  294. pub fn new_p2pk(pubkey: PublicKey, conditions: Option<Conditions>) -> Self {
  295. Self::P2PKConditions {
  296. data: pubkey,
  297. conditions,
  298. }
  299. }
  300. /// Kind of [SpendingConditions]
  301. pub fn kind(&self) -> Kind {
  302. match self {
  303. Self::P2PKConditions { .. } => Kind::P2PK,
  304. Self::HTLCConditions { .. } => Kind::HTLC,
  305. }
  306. }
  307. /// Number if signatures required to unlock
  308. pub fn num_sigs(&self) -> Option<u64> {
  309. match self {
  310. Self::P2PKConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.num_sigs),
  311. Self::HTLCConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.num_sigs),
  312. }
  313. }
  314. /// Public keys of locked [`Proof`]
  315. pub fn pubkeys(&self) -> Option<Vec<PublicKey>> {
  316. match self {
  317. Self::P2PKConditions { data, conditions } => {
  318. let mut pubkeys = vec![*data];
  319. if let Some(conditions) = conditions {
  320. pubkeys.extend(conditions.pubkeys.clone().unwrap_or_default());
  321. }
  322. // Remove duplicates
  323. let unique_pubkeys: HashSet<_> = pubkeys.into_iter().collect();
  324. Some(unique_pubkeys.into_iter().collect())
  325. }
  326. Self::HTLCConditions { conditions, .. } => conditions.clone().and_then(|c| c.pubkeys),
  327. }
  328. }
  329. /// Locktime of Spending Conditions
  330. pub fn locktime(&self) -> Option<u64> {
  331. match self {
  332. Self::P2PKConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.locktime),
  333. Self::HTLCConditions { conditions, .. } => conditions.as_ref().and_then(|c| c.locktime),
  334. }
  335. }
  336. /// Refund keys
  337. pub fn refund_keys(&self) -> Option<Vec<PublicKey>> {
  338. match self {
  339. Self::P2PKConditions { conditions, .. } => {
  340. conditions.clone().and_then(|c| c.refund_keys)
  341. }
  342. Self::HTLCConditions { conditions, .. } => {
  343. conditions.clone().and_then(|c| c.refund_keys)
  344. }
  345. }
  346. }
  347. }
  348. impl TryFrom<&Secret> for SpendingConditions {
  349. type Error = Error;
  350. fn try_from(secret: &Secret) -> Result<SpendingConditions, Error> {
  351. let nut10_secret: Nut10Secret = secret.try_into()?;
  352. nut10_secret.try_into()
  353. }
  354. }
  355. impl TryFrom<Nut10Secret> for SpendingConditions {
  356. type Error = Error;
  357. fn try_from(secret: Nut10Secret) -> Result<SpendingConditions, Error> {
  358. match secret.kind() {
  359. Kind::P2PK => Ok(SpendingConditions::P2PKConditions {
  360. data: PublicKey::from_str(secret.secret_data().data())?,
  361. conditions: secret
  362. .secret_data()
  363. .tags()
  364. .and_then(|t| t.clone().try_into().ok()),
  365. }),
  366. Kind::HTLC => Ok(Self::HTLCConditions {
  367. data: Sha256Hash::from_str(secret.secret_data().data())
  368. .map_err(|_| Error::InvalidHash)?,
  369. conditions: secret
  370. .secret_data()
  371. .tags()
  372. .and_then(|t| t.clone().try_into().ok()),
  373. }),
  374. }
  375. }
  376. }
  377. impl From<SpendingConditions> for super::nut10::Secret {
  378. fn from(conditions: SpendingConditions) -> super::nut10::Secret {
  379. match conditions {
  380. SpendingConditions::P2PKConditions { data, conditions } => {
  381. super::nut10::Secret::new(Kind::P2PK, data.to_hex(), conditions)
  382. }
  383. SpendingConditions::HTLCConditions { data, conditions } => {
  384. super::nut10::Secret::new(Kind::HTLC, data.to_string(), conditions)
  385. }
  386. }
  387. }
  388. }
  389. /// P2PK and HTLC spending conditions
  390. #[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
  391. pub struct Conditions {
  392. /// Unix locktime after which refund keys can be used
  393. #[serde(skip_serializing_if = "Option::is_none")]
  394. pub locktime: Option<u64>,
  395. /// Additional Public keys
  396. #[serde(skip_serializing_if = "Option::is_none")]
  397. pub pubkeys: Option<Vec<PublicKey>>,
  398. /// Refund keys
  399. #[serde(skip_serializing_if = "Option::is_none")]
  400. pub refund_keys: Option<Vec<PublicKey>>,
  401. /// Number of signatures required
  402. ///
  403. /// Default is 1
  404. #[serde(skip_serializing_if = "Option::is_none")]
  405. pub num_sigs: Option<u64>,
  406. /// Signature flag
  407. ///
  408. /// Default [`SigFlag::SigInputs`]
  409. pub sig_flag: SigFlag,
  410. /// Number of refund signatures required
  411. ///
  412. /// Default is 1
  413. #[serde(skip_serializing_if = "Option::is_none")]
  414. pub num_sigs_refund: Option<u64>,
  415. }
  416. impl Conditions {
  417. /// Create new Spending [`Conditions`]
  418. pub fn new(
  419. locktime: Option<u64>,
  420. pubkeys: Option<Vec<PublicKey>>,
  421. refund_keys: Option<Vec<PublicKey>>,
  422. num_sigs: Option<u64>,
  423. sig_flag: Option<SigFlag>,
  424. num_sigs_refund: Option<u64>,
  425. ) -> Result<Self, Error> {
  426. if let Some(locktime) = locktime {
  427. ensure_cdk!(locktime.ge(&unix_time()), Error::LocktimeInPast);
  428. }
  429. Ok(Self {
  430. locktime,
  431. pubkeys,
  432. refund_keys,
  433. num_sigs,
  434. sig_flag: sig_flag.unwrap_or_default(),
  435. num_sigs_refund,
  436. })
  437. }
  438. }
  439. impl From<Conditions> for Vec<Vec<String>> {
  440. fn from(conditions: Conditions) -> Vec<Vec<String>> {
  441. let Conditions {
  442. locktime,
  443. pubkeys,
  444. refund_keys,
  445. num_sigs,
  446. sig_flag,
  447. num_sigs_refund,
  448. } = conditions;
  449. let mut tags = Vec::new();
  450. if let Some(pubkeys) = pubkeys {
  451. tags.push(Tag::PubKeys(pubkeys.into_iter().collect()).as_vec());
  452. }
  453. if let Some(locktime) = locktime {
  454. tags.push(Tag::LockTime(locktime).as_vec());
  455. }
  456. if let Some(num_sigs) = num_sigs {
  457. tags.push(Tag::NSigs(num_sigs).as_vec());
  458. }
  459. if let Some(refund_keys) = refund_keys {
  460. tags.push(Tag::Refund(refund_keys).as_vec())
  461. }
  462. if let Some(num_sigs_refund) = num_sigs_refund {
  463. tags.push(Tag::NSigsRefund(num_sigs_refund).as_vec())
  464. }
  465. tags.push(Tag::SigFlag(sig_flag).as_vec());
  466. tags
  467. }
  468. }
  469. impl TryFrom<Vec<Vec<String>>> for Conditions {
  470. type Error = Error;
  471. fn try_from(tags: Vec<Vec<String>>) -> Result<Conditions, Self::Error> {
  472. let tags: HashMap<TagKind, Tag> = tags
  473. .into_iter()
  474. .map(|t| Tag::try_from(t).map(|tag| (tag.kind(), tag)))
  475. .collect::<Result<_, _>>()?;
  476. let pubkeys = match tags.get(&TagKind::Pubkeys) {
  477. Some(Tag::PubKeys(pubkeys)) => Some(pubkeys.clone()),
  478. _ => None,
  479. };
  480. let locktime = if let Some(tag) = tags.get(&TagKind::Locktime) {
  481. match tag {
  482. Tag::LockTime(locktime) => Some(*locktime),
  483. _ => None,
  484. }
  485. } else {
  486. None
  487. };
  488. let refund_keys = if let Some(tag) = tags.get(&TagKind::Refund) {
  489. match tag {
  490. Tag::Refund(keys) => Some(keys.clone()),
  491. _ => None,
  492. }
  493. } else {
  494. None
  495. };
  496. let sig_flag = if let Some(tag) = tags.get(&TagKind::SigFlag) {
  497. match tag {
  498. Tag::SigFlag(sigflag) => *sigflag,
  499. _ => SigFlag::SigInputs,
  500. }
  501. } else {
  502. SigFlag::SigInputs
  503. };
  504. let num_sigs = if let Some(tag) = tags.get(&TagKind::NSigs) {
  505. match tag {
  506. Tag::NSigs(num_sigs) => Some(*num_sigs),
  507. _ => None,
  508. }
  509. } else {
  510. None
  511. };
  512. let num_sigs_refund = if let Some(tag) = tags.get(&TagKind::NSigsRefund) {
  513. match tag {
  514. Tag::NSigsRefund(num_sigs) => Some(*num_sigs),
  515. _ => None,
  516. }
  517. } else {
  518. None
  519. };
  520. Ok(Conditions {
  521. locktime,
  522. pubkeys,
  523. refund_keys,
  524. num_sigs,
  525. sig_flag,
  526. num_sigs_refund,
  527. })
  528. }
  529. }
  530. /// P2PK and HTLC Spending condition tags
  531. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
  532. #[serde(rename_all = "lowercase")]
  533. pub enum TagKind {
  534. /// Signature flag
  535. SigFlag,
  536. /// Number signatures required
  537. #[serde(rename = "n_sigs")]
  538. NSigs,
  539. /// Locktime
  540. Locktime,
  541. /// Refund
  542. Refund,
  543. /// Pubkey
  544. Pubkeys,
  545. /// Number signatures required
  546. #[serde(rename = "n_sigs_refund")]
  547. NSigsRefund,
  548. /// Custom tag kind
  549. Custom(String),
  550. }
  551. impl fmt::Display for TagKind {
  552. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  553. match self {
  554. Self::SigFlag => write!(f, "sigflag"),
  555. Self::NSigs => write!(f, "n_sigs"),
  556. Self::Locktime => write!(f, "locktime"),
  557. Self::Refund => write!(f, "refund"),
  558. Self::Pubkeys => write!(f, "pubkeys"),
  559. Self::NSigsRefund => write!(f, "n_sigs_refund"),
  560. Self::Custom(c) => write!(f, "{c}"),
  561. }
  562. }
  563. }
  564. impl<S> From<S> for TagKind
  565. where
  566. S: AsRef<str>,
  567. {
  568. fn from(tag: S) -> Self {
  569. match tag.as_ref() {
  570. "sigflag" => Self::SigFlag,
  571. "n_sigs" => Self::NSigs,
  572. "locktime" => Self::Locktime,
  573. "refund" => Self::Refund,
  574. "pubkeys" => Self::Pubkeys,
  575. "n_sigs_refund" => Self::NSigsRefund,
  576. t => Self::Custom(t.to_owned()),
  577. }
  578. }
  579. }
  580. /// Signature flag
  581. ///
  582. /// Defined in [NUT11](https://github.com/cashubtc/nuts/blob/main/11.md)
  583. #[derive(
  584. Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash,
  585. )]
  586. pub enum SigFlag {
  587. #[default]
  588. /// Requires valid signatures on all inputs.
  589. /// It is the default signature flag and will be applied even if the
  590. /// `sigflag` tag is absent.
  591. SigInputs,
  592. /// Requires valid signatures on all inputs and on all outputs.
  593. SigAll,
  594. }
  595. impl fmt::Display for SigFlag {
  596. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  597. match self {
  598. Self::SigAll => write!(f, "SIG_ALL"),
  599. Self::SigInputs => write!(f, "SIG_INPUTS"),
  600. }
  601. }
  602. }
  603. impl FromStr for SigFlag {
  604. type Err = Error;
  605. fn from_str(tag: &str) -> Result<Self, Self::Err> {
  606. match tag {
  607. "SIG_ALL" => Ok(Self::SigAll),
  608. "SIG_INPUTS" => Ok(Self::SigInputs),
  609. _ => Err(Error::UnknownSigFlag),
  610. }
  611. }
  612. }
  613. /// Get the signature flag that should be enforced for a set of proofs and the
  614. /// public keys that signatures are valid for
  615. pub fn enforce_sig_flag(proofs: Proofs) -> EnforceSigFlag {
  616. let mut sig_flag = SigFlag::SigInputs;
  617. let mut pubkeys = HashSet::new();
  618. let mut sigs_required = 1;
  619. for proof in proofs {
  620. if let Ok(secret) = Nut10Secret::try_from(proof.secret) {
  621. if secret.kind().eq(&Kind::P2PK) {
  622. if let Ok(verifying_key) = PublicKey::from_str(secret.secret_data().data()) {
  623. pubkeys.insert(verifying_key);
  624. }
  625. }
  626. if let Some(tags) = secret.secret_data().tags() {
  627. if let Ok(conditions) = Conditions::try_from(tags.clone()) {
  628. if conditions.sig_flag.eq(&SigFlag::SigAll) {
  629. sig_flag = SigFlag::SigAll;
  630. }
  631. if let Some(sigs) = conditions.num_sigs {
  632. if sigs > sigs_required {
  633. sigs_required = sigs;
  634. }
  635. }
  636. if let Some(pubs) = conditions.pubkeys {
  637. pubkeys.extend(pubs);
  638. }
  639. }
  640. }
  641. }
  642. }
  643. EnforceSigFlag {
  644. sig_flag,
  645. pubkeys,
  646. sigs_required,
  647. }
  648. }
  649. /// Enforce Sigflag info
  650. #[derive(Debug, Clone, PartialEq, Eq)]
  651. pub struct EnforceSigFlag {
  652. /// Sigflag required for proofs
  653. pub sig_flag: SigFlag,
  654. /// Pubkeys that can sign for proofs
  655. pub pubkeys: HashSet<PublicKey>,
  656. /// Number of sigs required for proofs
  657. pub sigs_required: u64,
  658. }
  659. /// Tag
  660. #[derive(Debug, Clone, Hash, PartialEq, Eq)]
  661. pub enum Tag {
  662. /// Sigflag [`Tag`]
  663. SigFlag(SigFlag),
  664. /// Number of Sigs [`Tag`]
  665. NSigs(u64),
  666. /// Locktime [`Tag`]
  667. LockTime(u64),
  668. /// Refund [`Tag`]
  669. Refund(Vec<PublicKey>),
  670. /// Pubkeys [`Tag`]
  671. PubKeys(Vec<PublicKey>),
  672. /// Number of Sigs refund [`Tag`]
  673. NSigsRefund(u64),
  674. /// Custom tag
  675. Custom(String, Vec<String>),
  676. }
  677. impl Tag {
  678. /// Get [`Tag`] Kind
  679. pub fn kind(&self) -> TagKind {
  680. match self {
  681. Self::SigFlag(_) => TagKind::SigFlag,
  682. Self::NSigs(_) => TagKind::NSigs,
  683. Self::LockTime(_) => TagKind::Locktime,
  684. Self::Refund(_) => TagKind::Refund,
  685. Self::PubKeys(_) => TagKind::Pubkeys,
  686. Self::NSigsRefund(_) => TagKind::NSigsRefund,
  687. Self::Custom(tag, _) => TagKind::Custom(tag.to_string()),
  688. }
  689. }
  690. /// Get [`Tag`] as string vector
  691. pub fn as_vec(&self) -> Vec<String> {
  692. self.clone().into()
  693. }
  694. }
  695. impl<S> TryFrom<Vec<S>> for Tag
  696. where
  697. S: AsRef<str>,
  698. {
  699. type Error = Error;
  700. fn try_from(tag: Vec<S>) -> Result<Self, Self::Error> {
  701. let tag_kind = tag.first().map(TagKind::from).ok_or(Error::KindNotFound)?;
  702. match tag_kind {
  703. TagKind::SigFlag => Ok(Tag::SigFlag(SigFlag::from_str(tag[1].as_ref())?)),
  704. TagKind::NSigs => Ok(Tag::NSigs(tag[1].as_ref().parse()?)),
  705. TagKind::Locktime => Ok(Tag::LockTime(tag[1].as_ref().parse()?)),
  706. TagKind::Refund => {
  707. let pubkeys = tag
  708. .iter()
  709. .skip(1)
  710. .map(|p| PublicKey::from_str(p.as_ref()))
  711. .collect::<Result<Vec<PublicKey>, _>>()?;
  712. Ok(Self::Refund(pubkeys))
  713. }
  714. TagKind::Pubkeys => {
  715. let pubkeys = tag
  716. .iter()
  717. .skip(1)
  718. .map(|p| PublicKey::from_str(p.as_ref()))
  719. .collect::<Result<Vec<PublicKey>, _>>()?;
  720. Ok(Self::PubKeys(pubkeys))
  721. }
  722. TagKind::NSigsRefund => Ok(Tag::NSigsRefund(tag[1].as_ref().parse()?)),
  723. TagKind::Custom(name) => {
  724. let tags = tag
  725. .iter()
  726. .skip(1)
  727. .map(|p| p.as_ref().to_string())
  728. .collect::<Vec<String>>();
  729. Ok(Self::Custom(name, tags))
  730. }
  731. }
  732. }
  733. }
  734. impl From<Tag> for Vec<String> {
  735. fn from(data: Tag) -> Self {
  736. match data {
  737. Tag::SigFlag(sigflag) => vec![TagKind::SigFlag.to_string(), sigflag.to_string()],
  738. Tag::NSigs(num_sig) => vec![TagKind::NSigs.to_string(), num_sig.to_string()],
  739. Tag::LockTime(locktime) => vec![TagKind::Locktime.to_string(), locktime.to_string()],
  740. Tag::PubKeys(pubkeys) => {
  741. let mut tag = vec![TagKind::Pubkeys.to_string()];
  742. for pubkey in pubkeys.into_iter() {
  743. tag.push(pubkey.to_string())
  744. }
  745. tag
  746. }
  747. Tag::Refund(pubkeys) => {
  748. let mut tag = vec![TagKind::Refund.to_string()];
  749. for pubkey in pubkeys {
  750. tag.push(pubkey.to_string())
  751. }
  752. tag
  753. }
  754. Tag::NSigsRefund(num_sigs) => {
  755. vec![TagKind::NSigsRefund.to_string(), num_sigs.to_string()]
  756. }
  757. Tag::Custom(name, c) => {
  758. let mut tag = vec![name];
  759. for t in c {
  760. tag.push(t);
  761. }
  762. tag
  763. }
  764. }
  765. }
  766. }
  767. impl SwapRequest {
  768. /// Sign swap request with SIG_ALL
  769. pub fn sign_sig_all(&mut self, secret_key: SecretKey) -> Result<(), Error> {
  770. // Get message to sign
  771. let msg = self.sig_all_msg_to_sign();
  772. let signature = secret_key.sign(msg.as_bytes())?;
  773. // Add signature to first input witness
  774. let first_input = self
  775. .inputs_mut()
  776. .first_mut()
  777. .ok_or(Error::IncorrectSecretKind)?;
  778. match first_input.witness.as_mut() {
  779. Some(witness) => {
  780. witness.add_signatures(vec![signature.to_string()]);
  781. }
  782. None => {
  783. let mut p2pk_witness = Witness::P2PKWitness(P2PKWitness::default());
  784. p2pk_witness.add_signatures(vec![signature.to_string()]);
  785. first_input.witness = Some(p2pk_witness);
  786. }
  787. };
  788. Ok(())
  789. }
  790. }
  791. impl<Q> MeltRequest<Q>
  792. where
  793. Q: std::fmt::Display + Serialize + DeserializeOwned,
  794. {
  795. /// Sign melt request with SIG_ALL
  796. pub fn sign_sig_all(&mut self, secret_key: SecretKey) -> Result<(), Error> {
  797. // Get message to sign
  798. let msg = self.sig_all_msg_to_sign();
  799. let signature = secret_key.sign(msg.as_bytes())?;
  800. // Add signature to first input witness
  801. let first_input = self
  802. .inputs_mut()
  803. .first_mut()
  804. .ok_or(Error::SpendConditionsNotMet)?;
  805. match first_input.witness.as_mut() {
  806. Some(witness) => {
  807. witness.add_signatures(vec![signature.to_string()]);
  808. }
  809. None => {
  810. let mut p2pk_witness = Witness::P2PKWitness(P2PKWitness::default());
  811. p2pk_witness.add_signatures(vec![signature.to_string()]);
  812. first_input.witness = Some(p2pk_witness);
  813. }
  814. };
  815. Ok(())
  816. }
  817. }
  818. impl Serialize for Tag {
  819. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  820. where
  821. S: Serializer,
  822. {
  823. let data: Vec<String> = self.as_vec();
  824. let mut seq = serializer.serialize_seq(Some(data.len()))?;
  825. for element in data.into_iter() {
  826. seq.serialize_element(&element)?;
  827. }
  828. seq.end()
  829. }
  830. }
  831. impl<'de> Deserialize<'de> for Tag {
  832. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  833. where
  834. D: Deserializer<'de>,
  835. {
  836. type Data = Vec<String>;
  837. let vec: Vec<String> = Data::deserialize(deserializer)?;
  838. Self::try_from(vec).map_err(DeserializerError::custom)
  839. }
  840. }
  841. #[cfg(feature = "mint")]
  842. #[cfg(test)]
  843. mod tests {
  844. use std::str::FromStr;
  845. use uuid::Uuid;
  846. use super::*;
  847. use crate::nuts::Id;
  848. use crate::quote_id::QuoteId;
  849. use crate::secret::Secret;
  850. use crate::{Amount, BlindedMessage};
  851. #[test]
  852. fn test_secret_ser() {
  853. let data = PublicKey::from_str(
  854. "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
  855. )
  856. .unwrap();
  857. let conditions = Conditions {
  858. locktime: Some(99999),
  859. pubkeys: Some(vec![
  860. PublicKey::from_str(
  861. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  862. )
  863. .unwrap(),
  864. PublicKey::from_str(
  865. "023192200a0cfd3867e48eb63b03ff599c7e46c8f4e41146b2d281173ca6c50c54",
  866. )
  867. .unwrap(),
  868. ]),
  869. refund_keys: Some(vec![PublicKey::from_str(
  870. "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
  871. )
  872. .unwrap()]),
  873. num_sigs: Some(2),
  874. sig_flag: SigFlag::SigAll,
  875. num_sigs_refund: None,
  876. };
  877. let secret: Nut10Secret = Nut10Secret::new(Kind::P2PK, data.to_string(), Some(conditions));
  878. let secret_str = serde_json::to_string(&secret).unwrap();
  879. let secret_der: Nut10Secret = serde_json::from_str(&secret_str).unwrap();
  880. assert_eq!(secret_der, secret);
  881. }
  882. #[test]
  883. fn sign_proof() {
  884. let secret_key =
  885. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  886. .unwrap();
  887. let signing_key_two =
  888. SecretKey::from_str("0000000000000000000000000000000000000000000000000000000000000001")
  889. .unwrap();
  890. let signing_key_three =
  891. SecretKey::from_str("7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f")
  892. .unwrap();
  893. let v_key: PublicKey = secret_key.public_key();
  894. let v_key_two: PublicKey = signing_key_two.public_key();
  895. let v_key_three: PublicKey = signing_key_three.public_key();
  896. let conditions = Conditions {
  897. locktime: Some(21000000000),
  898. pubkeys: Some(vec![v_key_two, v_key_three]),
  899. refund_keys: Some(vec![v_key]),
  900. num_sigs: Some(2),
  901. sig_flag: SigFlag::SigInputs,
  902. num_sigs_refund: None,
  903. };
  904. let secret: Secret = Nut10Secret::new(Kind::P2PK, v_key.to_string(), Some(conditions))
  905. .try_into()
  906. .unwrap();
  907. let mut proof = Proof {
  908. keyset_id: Id::from_str("009a1f293253e41e").unwrap(),
  909. amount: Amount::ZERO,
  910. secret,
  911. c: PublicKey::from_str(
  912. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  913. )
  914. .unwrap(),
  915. witness: Some(Witness::P2PKWitness(P2PKWitness { signatures: vec![] })),
  916. dleq: None,
  917. };
  918. proof.sign_p2pk(secret_key).unwrap();
  919. proof.sign_p2pk(signing_key_two).unwrap();
  920. assert!(proof.verify_p2pk().is_ok());
  921. }
  922. #[test]
  923. fn test_verify() {
  924. // Proof with a valid signature
  925. let json: &str = r#"{
  926. "amount":1,
  927. "secret":"[\"P2PK\",{\"nonce\":\"859d4935c4907062a6297cf4e663e2835d90d97ecdd510745d32f6816323a41f\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_INPUTS\"]]}]",
  928. "C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  929. "id":"009a1f293253e41e",
  930. "witness":"{\"signatures\":[\"60f3c9b766770b46caac1d27e1ae6b77c8866ebaeba0b9489fe6a15a837eaa6fcd6eaa825499c72ac342983983fd3ba3a8a41f56677cc99ffd73da68b59e1383\"]}"
  931. }"#;
  932. let valid_proof: Proof = serde_json::from_str(json).unwrap();
  933. valid_proof.verify_p2pk().unwrap();
  934. assert!(valid_proof.verify_p2pk().is_ok());
  935. // Proof with a signature that is in a different secret
  936. let invalid_proof = r#"{"amount":1,"secret":"[\"P2PK\",{\"nonce\":\"859d4935c4907062a6297cf4e663e2835d90d97ecdd510745d32f6816323a41f\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","id":"009a1f293253e41e","witness":"{\"signatures\":[\"3426df9730d365a9d18d79bed2f3e78e9172d7107c55306ac5ddd1b2d065893366cfa24ff3c874ebf1fc22360ba5888ddf6ff5dbcb9e5f2f5a1368f7afc64f15\"]}"}"#;
  937. let invalid_proof: Proof = serde_json::from_str(invalid_proof).unwrap();
  938. assert!(invalid_proof.verify_p2pk().is_err());
  939. }
  940. #[test]
  941. fn verify_multi_sig() {
  942. // Proof with 2 valid signatures to satifiy the condition
  943. 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\"]}"}"#;
  944. let valid_proof: Proof = serde_json::from_str(valid_proof).unwrap();
  945. assert!(valid_proof.verify_p2pk().is_ok());
  946. // Proof with only one of the required signatures
  947. 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\"]}"}"#;
  948. let invalid_proof: Proof = serde_json::from_str(invalid_proof).unwrap();
  949. // Verification should fail without the requires signatures
  950. assert!(invalid_proof.verify_p2pk().is_err());
  951. }
  952. #[test]
  953. fn verify_refund() {
  954. 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\"]}"}"#;
  955. let valid_proof: Proof = serde_json::from_str(valid_proof).unwrap();
  956. assert!(valid_proof.verify_p2pk().is_ok());
  957. 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\"]}"}"#;
  958. let invalid_proof: Proof = serde_json::from_str(invalid_proof).unwrap();
  959. assert!(invalid_proof.verify_p2pk().is_err());
  960. }
  961. #[test]
  962. fn sig_with_non_refund_keys_after_locktime() {
  963. let secret_key =
  964. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  965. .unwrap();
  966. let signing_key_two =
  967. SecretKey::from_str("0000000000000000000000000000000000000000000000000000000000000001")
  968. .unwrap();
  969. let signing_key_three =
  970. SecretKey::from_str("7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f")
  971. .unwrap();
  972. let v_key: PublicKey = secret_key.public_key();
  973. let v_key_two: PublicKey = signing_key_two.public_key();
  974. let v_key_three: PublicKey = signing_key_three.public_key();
  975. let conditions = Conditions {
  976. locktime: Some(21),
  977. pubkeys: Some(vec![v_key_three]),
  978. refund_keys: Some(vec![v_key, v_key_two]),
  979. num_sigs: None,
  980. sig_flag: SigFlag::SigInputs,
  981. num_sigs_refund: Some(2),
  982. };
  983. let secret: Secret = Nut10Secret::new(Kind::P2PK, v_key.to_string(), Some(conditions))
  984. .try_into()
  985. .unwrap();
  986. let mut proof = Proof {
  987. keyset_id: Id::from_str("009a1f293253e41e").unwrap(),
  988. amount: Amount::ZERO,
  989. secret,
  990. c: PublicKey::from_str(
  991. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  992. )
  993. .unwrap(),
  994. witness: Some(Witness::P2PKWitness(P2PKWitness { signatures: vec![] })),
  995. dleq: None,
  996. };
  997. proof.sign_p2pk(signing_key_three.clone()).unwrap();
  998. assert!(proof.verify_p2pk().is_err());
  999. proof.witness = None;
  1000. proof.sign_p2pk(secret_key).unwrap();
  1001. assert!(proof.verify_p2pk().is_err());
  1002. proof.sign_p2pk(signing_key_two).unwrap();
  1003. assert!(proof.verify_p2pk().is_ok());
  1004. }
  1005. // Helper functions for melt request tests
  1006. fn create_test_proof(secret: Secret, pubkey: PublicKey, id: &str) -> Proof {
  1007. Proof {
  1008. keyset_id: Id::from_str(id).unwrap(),
  1009. amount: Amount::ZERO,
  1010. secret,
  1011. c: pubkey,
  1012. witness: None,
  1013. dleq: None,
  1014. }
  1015. }
  1016. fn create_test_secret(pubkey: PublicKey, conditions: Conditions) -> Secret {
  1017. Nut10Secret::new(Kind::P2PK, pubkey.to_string(), Some(conditions))
  1018. .try_into()
  1019. .unwrap()
  1020. }
  1021. fn create_test_blinded_msg(pubkey: PublicKey) -> BlindedMessage {
  1022. BlindedMessage {
  1023. amount: Amount::ZERO,
  1024. blinded_secret: pubkey,
  1025. keyset_id: Id::from_str("009a1f293253e41e").unwrap(),
  1026. witness: None,
  1027. }
  1028. }
  1029. #[test]
  1030. fn test_melt_sig_all_basic_signing() {
  1031. let secret_key =
  1032. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1033. .unwrap();
  1034. let pubkey = secret_key.public_key();
  1035. // Create conditions with SIG_ALL
  1036. let conditions = Conditions {
  1037. sig_flag: SigFlag::SigAll,
  1038. ..Default::default()
  1039. };
  1040. let secret = create_test_secret(pubkey, conditions);
  1041. let proof = create_test_proof(secret, pubkey, "009a1f293253e41e");
  1042. let blinded_msg = create_test_blinded_msg(pubkey);
  1043. // Create melt request
  1044. let mut melt = MeltRequest::new(
  1045. QuoteId::UUID(Uuid::new_v4()),
  1046. vec![proof],
  1047. Some(vec![blinded_msg]),
  1048. );
  1049. // Before signing, should fail verification
  1050. assert!(
  1051. melt.verify_spending_conditions().is_err(),
  1052. "Unsigned melt request should fail verification"
  1053. );
  1054. // Sign the request
  1055. assert!(
  1056. melt.sign_sig_all(secret_key).is_ok(),
  1057. "Signing should succeed"
  1058. );
  1059. // After signing, should pass verification
  1060. assert!(
  1061. melt.verify_spending_conditions().is_ok(),
  1062. "Signed melt request should pass verification"
  1063. );
  1064. }
  1065. #[test]
  1066. fn test_melt_sig_all_unauthorized_key() {
  1067. let secret_key =
  1068. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1069. .unwrap();
  1070. let pubkey = secret_key.public_key();
  1071. // Create conditions with explicit authorized pubkey
  1072. let conditions = Conditions {
  1073. sig_flag: SigFlag::SigAll,
  1074. pubkeys: Some(vec![pubkey]),
  1075. ..Default::default()
  1076. };
  1077. let secret = create_test_secret(pubkey, conditions);
  1078. let proof = create_test_proof(secret, pubkey, "009a1f293253e41e");
  1079. let mut melt = MeltRequest::new(Uuid::new_v4(), vec![proof], None);
  1080. // Sign with unauthorized key
  1081. let unauthorized_key =
  1082. SecretKey::from_str("0000000000000000000000000000000000000000000000000000000000000001")
  1083. .unwrap();
  1084. melt.sign_sig_all(unauthorized_key).unwrap();
  1085. // Verification should fail (unauthorized signature)
  1086. assert!(
  1087. melt.verify_spending_conditions().is_err(),
  1088. "Verification should fail with unauthorized key signature"
  1089. );
  1090. }
  1091. #[test]
  1092. fn test_melt_sig_all_wrong_flag() {
  1093. let secret_key =
  1094. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1095. .unwrap();
  1096. let pubkey = secret_key.public_key();
  1097. // Create conditions with SIG_INPUTS instead of SIG_ALL
  1098. let conditions = Conditions {
  1099. sig_flag: SigFlag::SigInputs,
  1100. pubkeys: Some(vec![pubkey]),
  1101. ..Default::default()
  1102. };
  1103. let secret = create_test_secret(pubkey, conditions);
  1104. let proof = create_test_proof(secret, pubkey, "009a1f293253e41e");
  1105. let mut melt = MeltRequest::new(Uuid::new_v4(), vec![proof], None);
  1106. // Signing
  1107. melt.sign_sig_all(secret_key).unwrap();
  1108. // Verification should fail (wrong flag - expected SIG_ALL)
  1109. assert!(
  1110. melt.verify_spending_conditions().is_err(),
  1111. "Verification should fail with SIG_INPUTS flag when expecting SIG_ALL"
  1112. );
  1113. }
  1114. #[test]
  1115. fn test_melt_sig_all_multiple_inputs() {
  1116. let secret_key =
  1117. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1118. .unwrap();
  1119. let pubkey = secret_key.public_key();
  1120. // Create conditions
  1121. let conditions = Conditions {
  1122. sig_flag: SigFlag::SigAll,
  1123. ..Default::default()
  1124. };
  1125. let secret = create_test_secret(pubkey, conditions);
  1126. // Create two proofs with same secret
  1127. let proof1 = create_test_proof(secret.clone(), pubkey, "009a1f293253e41e");
  1128. let proof2 = create_test_proof(secret, pubkey, "009a1f293253e41f");
  1129. let mut melt = MeltRequest::new(Uuid::new_v4(), vec![proof1, proof2], None);
  1130. // Signing should work with multiple matching inputs
  1131. assert!(
  1132. melt.sign_sig_all(secret_key).is_ok(),
  1133. "Signing with multiple matching inputs should succeed"
  1134. );
  1135. assert!(
  1136. melt.verify_spending_conditions().is_ok(),
  1137. "Verification should succeed with multiple matching inputs"
  1138. );
  1139. }
  1140. #[test]
  1141. fn test_melt_sig_all_mismatched_inputs() {
  1142. let secret_key =
  1143. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1144. .unwrap();
  1145. let pubkey = secret_key.public_key();
  1146. // Create first secret and proof
  1147. let conditions1 = Conditions {
  1148. sig_flag: SigFlag::SigAll,
  1149. ..Default::default()
  1150. };
  1151. let secret1 = create_test_secret(pubkey, conditions1.clone());
  1152. let proof1 = create_test_proof(secret1, pubkey, "009a1f293253e41e");
  1153. // Create second secret with different data
  1154. let conditions2 = conditions1.clone();
  1155. let secret2 = Nut10Secret::new(
  1156. Kind::P2PK,
  1157. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  1158. Some(conditions2),
  1159. )
  1160. .try_into()
  1161. .unwrap();
  1162. let proof2 = create_test_proof(secret2, pubkey, "009a1f293253e41f");
  1163. let mut melt = MeltRequest::new(Uuid::new_v4(), vec![proof1, proof2], None);
  1164. // Signing should succeed (no validation during signing)
  1165. melt.sign_sig_all(secret_key).unwrap();
  1166. // Verification should fail (catches mismatched inputs)
  1167. assert!(
  1168. melt.verify_spending_conditions().is_err(),
  1169. "Verification should fail with mismatched input secrets"
  1170. );
  1171. }
  1172. #[test]
  1173. fn test_melt_sig_all_multiple_signatures() {
  1174. let secret_key1 =
  1175. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1176. .unwrap();
  1177. let pubkey1 = secret_key1.public_key();
  1178. let secret_key2 =
  1179. SecretKey::from_str("7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f")
  1180. .unwrap();
  1181. let pubkey2 = secret_key2.public_key();
  1182. // Create conditions requiring 2 signatures
  1183. let conditions = Conditions {
  1184. sig_flag: SigFlag::SigAll,
  1185. num_sigs: Some(2),
  1186. pubkeys: Some(vec![pubkey2]),
  1187. ..Default::default()
  1188. };
  1189. let secret = create_test_secret(pubkey1, conditions);
  1190. let proof = create_test_proof(secret, pubkey1, "009a1f293253e41e");
  1191. let mut melt = MeltRequest::new(
  1192. Uuid::new_v4(),
  1193. vec![proof],
  1194. Some(vec![create_test_blinded_msg(
  1195. SecretKey::generate().public_key(),
  1196. )]),
  1197. );
  1198. // First signature
  1199. assert!(
  1200. melt.sign_sig_all(secret_key1).is_ok(),
  1201. "First signature should succeed"
  1202. );
  1203. assert!(
  1204. melt.verify_spending_conditions().is_err(),
  1205. "Single signature should not verify when two required"
  1206. );
  1207. // Second signature
  1208. assert!(
  1209. melt.sign_sig_all(secret_key2).is_ok(),
  1210. "Second signature should succeed"
  1211. );
  1212. assert!(
  1213. melt.verify_spending_conditions().is_ok(),
  1214. "Both signatures should verify successfully"
  1215. );
  1216. }
  1217. #[test]
  1218. fn test_melt_sig_all_message_components() {
  1219. let secret_key =
  1220. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1221. .unwrap();
  1222. let pubkey = secret_key.public_key();
  1223. let conditions = Conditions {
  1224. sig_flag: SigFlag::SigAll,
  1225. pubkeys: Some(vec![pubkey]),
  1226. ..Default::default()
  1227. };
  1228. let secret = create_test_secret(pubkey, conditions);
  1229. let proof = create_test_proof(secret.clone(), pubkey, "009a1f293253e41e");
  1230. let blinded_msg = create_test_blinded_msg(pubkey);
  1231. let quote_id = Uuid::new_v4();
  1232. let melt = MeltRequest::new(quote_id, vec![proof], Some(vec![blinded_msg.clone()]));
  1233. // Get message to sign
  1234. let msg = melt.sig_all_msg_to_sign();
  1235. // Verify all components are present in the message
  1236. assert!(
  1237. msg.contains(&secret.to_string()),
  1238. "Message should contain secret"
  1239. );
  1240. assert!(
  1241. msg.contains(&blinded_msg.blinded_secret.to_hex()),
  1242. "Message should contain blinded message in hex format"
  1243. );
  1244. assert!(
  1245. msg.contains(&quote_id.to_string()),
  1246. "Message should contain quote ID"
  1247. );
  1248. }
  1249. // "SIG_ALL Test Vectors", starting with swaps : https://github.com/cashubtc/nuts/blob/5b050c7960607cca0481c28517cab5cc091b5d2e/tests/11-test.md#sig_all-test-vectors
  1250. #[test]
  1251. fn test_sig_all_swap_single_sig() {
  1252. // Valid SwapRequest with SIG_ALL signature
  1253. let valid_swap = r#"{
  1254. "inputs": [
  1255. {
  1256. "amount": 2,
  1257. "id": "00bfa73302d12ffd",
  1258. "secret": "[\"P2PK\",{\"nonce\":\"c7f280eb55c1e8564e03db06973e94bc9b666d9e1ca42ad278408fe625950303\",\"data\":\"030d8acedfe072c9fa449a1efe0817157403fbec460d8e79f957966056e5dd76c1\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]",
  1259. "C": "02c97ee3d1db41cf0a3ddb601724be8711a032950811bf326f8219c50c4808d3cd",
  1260. "witness": "{\"signatures\":[\"ce017ca25b1b97df2f72e4b49f69ac26a240ce14b3690a8fe619d41ccc42d3c1282e073f85acd36dc50011638906f35b56615f24e4d03e8effe8257f6a808538\"]}"
  1261. }
  1262. ],
  1263. "outputs": [
  1264. {
  1265. "amount": 2,
  1266. "id": "00bfa73302d12ffd",
  1267. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1268. }
  1269. ]
  1270. }"#;
  1271. let valid_swap: SwapRequest = serde_json::from_str(valid_swap).unwrap();
  1272. // Verify the message format
  1273. let msg_to_sign = valid_swap.sig_all_msg_to_sign();
  1274. assert_eq!(
  1275. msg_to_sign,
  1276. "[\"P2PK\",{\"nonce\":\"c7f280eb55c1e8564e03db06973e94bc9b666d9e1ca42ad278408fe625950303\",\"data\":\"030d8acedfe072c9fa449a1efe0817157403fbec460d8e79f957966056e5dd76c1\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]02c97ee3d1db41cf0a3ddb601724be8711a032950811bf326f8219c50c4808d3cd2038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1277. );
  1278. // Verify the SHA256 hash of the message
  1279. use bitcoin::hashes::{sha256, Hash};
  1280. let msg_hash = sha256::Hash::hash(msg_to_sign.as_bytes());
  1281. assert_eq!(
  1282. msg_hash.to_string(),
  1283. "de7f9e3ca0fcc5ed3258fcf83dbf1be7fa78a5ed6da7bf2aa60d61e9dc6eb09a"
  1284. );
  1285. assert!(
  1286. valid_swap.verify_spending_conditions().is_ok(),
  1287. "Valid SIG_ALL swap request should verify"
  1288. );
  1289. }
  1290. #[test]
  1291. fn test_sig_all_swap_single_sig_2() {
  1292. // The following is a SwapRequest with a valid sig_all signature.
  1293. let valid_swap = r#"{
  1294. "inputs": [
  1295. {
  1296. "amount": 2,
  1297. "id": "00bfa73302d12ffd",
  1298. "secret": "[\"P2PK\",{\"nonce\":\"c7f280eb55c1e8564e03db06973e94bc9b666d9e1ca42ad278408fe625950303\",\"data\":\"030d8acedfe072c9fa449a1efe0817157403fbec460d8e79f957966056e5dd76c1\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]",
  1299. "C": "02c97ee3d1db41cf0a3ddb601724be8711a032950811bf326f8219c50c4808d3cd",
  1300. "witness": "{\"signatures\":[\"ce017ca25b1b97df2f72e4b49f69ac26a240ce14b3690a8fe619d41ccc42d3c1282e073f85acd36dc50011638906f35b56615f24e4d03e8effe8257f6a808538\"]}"
  1301. }
  1302. ],
  1303. "outputs": [
  1304. {
  1305. "amount": 2,
  1306. "id": "00bfa73302d12ffd",
  1307. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1308. }
  1309. ]
  1310. }"#;
  1311. let valid_swap: SwapRequest = serde_json::from_str(valid_swap).unwrap();
  1312. assert!(
  1313. valid_swap.verify_spending_conditions().is_ok(),
  1314. "Valid SIG_ALL swap request should verify"
  1315. );
  1316. }
  1317. #[test]
  1318. fn test_sig_all_multiple_secrets() {
  1319. // The following is a SwapRequest that is invalid as there are multiple secrets.
  1320. let invalid_swap = r#"{
  1321. "inputs": [
  1322. {
  1323. "amount": 1,
  1324. "id": "00bfa73302d12ffd",
  1325. "secret": "[\"P2PK\",{\"nonce\":\"fa6dd3fac9086c153878dec90b9e37163d38ff2ecf8b37db6470e9d185abbbae\",\"data\":\"033b42b04e659fed13b669f8b16cdaffc3ee5738608810cf97a7631d09bd01399d\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]",
  1326. "C": "024d232312bab25af2e73f41d56864d378edca9109ae8f76e1030e02e585847786",
  1327. "witness": "{\"signatures\":[\"27b4d260a1186e3b62a26c0d14ffeab3b9f7c3889e78707b8fd3836b473a00601afbd53a2288ad20a624a8bbe3344453215ea075fc0ce479dd8666fd3d9162cc\"]}"
  1328. },
  1329. {
  1330. "amount": 2,
  1331. "id": "00bfa73302d12ffd",
  1332. "secret": "[\"P2PK\",{\"nonce\":\"4007b21fc5f5b1d4920bc0a08b158d98fd0fb2b0b0262b57ff53c6c5d6c2ae8c\",\"data\":\"033b42b04e659fed13b669f8b16cdaffc3ee5738608810cf97a7631d09bd01399d\",\"tags\":[[\"locktime\",\"122222222222222\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1333. "C": "02417400f2af09772219c831501afcbab4efb3b2e75175635d5474069608deb641"
  1334. }
  1335. ],
  1336. "outputs": [
  1337. {
  1338. "amount": 1,
  1339. "id": "00bfa73302d12ffd",
  1340. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1341. },
  1342. {
  1343. "amount": 1,
  1344. "id": "00bfa73302d12ffd",
  1345. "B_": "03afe7c87e32d436f0957f1d70a2bca025822a84a8623e3a33aed0a167016e0ca5"
  1346. },
  1347. {
  1348. "amount": 1,
  1349. "id": "00bfa73302d12ffd",
  1350. "B_": "02c0d4fce02a7a0f09e3f1bca952db910b17e81a7ebcbce62cd8dcfb127d21e37b"
  1351. }
  1352. ]
  1353. }"#;
  1354. let invalid_swap: SwapRequest = serde_json::from_str(invalid_swap).unwrap();
  1355. assert!(
  1356. invalid_swap.verify_spending_conditions().is_err(),
  1357. "Invalid swap with multiple secrets shouldn't be accepted"
  1358. );
  1359. }
  1360. #[test]
  1361. fn test_sig_all_multiple_signatures_provided() {
  1362. // The following is a SwapRequest multiple valid signatures are provided and required.
  1363. let valid_swap = r#"{
  1364. "inputs": [
  1365. {
  1366. "amount": 2,
  1367. "id": "00bfa73302d12ffd",
  1368. "secret": "[\"P2PK\",{\"nonce\":\"04bfd885fc982d553711092d037fdceb7320fd8f96b0d4fd6d31a65b83b94272\",\"data\":\"0275e78025b558dbe6cb8fdd032a2e7613ca14fda5c1f4c4e3427f5077a7bd90e4\",\"tags\":[[\"pubkeys\",\"035163650bbd5ed4be7693f40f340346ba548b941074e9138b67ef6c42755f3449\",\"02817d22a8edc44c4141e192995a7976647c335092199f9e076a170c7336e2f5cc\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1369. "C": "03866a09946562482c576ca989d06371e412b221890804c7da8887d321380755be",
  1370. "witness": "{\"signatures\":[\"be1d72c5ca16a93c5a34f25ec63ce632ddc3176787dac363321af3fd0f55d1927e07451bc451ffe5c682d76688ea9925d7977dffbb15bd79763b527f474734b0\",\"669d6d10d7ed35395009f222f6c7bdc28a378a1ebb72ee43117be5754648501da3bedf2fd6ff0c7849ac92683538c60af0af504102e40f2d8daca8e08b1ca16b\"]}"
  1371. }
  1372. ],
  1373. "outputs": [
  1374. {
  1375. "amount": 2,
  1376. "id": "00bfa73302d12ffd",
  1377. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1378. }
  1379. ]
  1380. }"#;
  1381. let valid_swap: SwapRequest = serde_json::from_str(valid_swap).unwrap();
  1382. assert!(
  1383. valid_swap.verify_spending_conditions().is_ok(),
  1384. "Valid swap with multiple signatures should be accepted"
  1385. );
  1386. }
  1387. #[test]
  1388. fn test_sig_all_mixed_pubkeys_and_refund() {
  1389. // The following is an invalid SwapRequest with pubkeys and refund mixed.
  1390. let invalid_swap = r#"{
  1391. "inputs": [
  1392. {
  1393. "amount": 2,
  1394. "id": "00bfa73302d12ffd",
  1395. "secret": "[\"P2PK\",{\"nonce\":\"3e9253419a11f0a541dd6baeddecf8356fc864b5d061f12f05632bc3aee6b5c4\",\"data\":\"0343cca0e48ce9e3fdcddba4637ff8cdbf6f5ed9cfdf1873e63827e760f0ed4db5\",\"tags\":[[\"pubkeys\",\"0235e0a719f8b046cee90f55a59b1cdd6ca75ce23e49cbcd82c9e5b7310e21ebcd\",\"020443f98b356e021bae82bdfc05ff433cab21e27fca9ab7b0995aedb2e7aabc43\"],[\"locktime\",\"100\"],[\"n_sigs\",\"2\"],[\"refund\",\"026b432e62b041bf9cdae534203739c73fa506c9a2d6aa58a52bc601a1dec421e1\",\"02e3494a2e07e7f6e7d4567e0da7a563592bff1e121df2383667f15b83e9168a9e\"],[\"n_sigs_refund\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1396. "C": "026c12ee3bffa5c617debcf823bf1af6a9b47145b699f2737bba3394f0893eb869",
  1397. "witness": "{\"signatures\":[\"bfe884145ce6512331324321c3946dfd812428a53656b108b59d26559a186ba2ab45e5be9ce94e2dff0d09078e25ccb82d06a8b3a63cd3dc67065b8f77292776\",\"236e5cc9c30f85a893a29a4302e41e6f2015caef4229f28fa65e2f5c9d55515cc9a1852093a81a5095055d85fd55bf4da124e55354b56e0a39e83b58b0afc197\"]}"
  1398. }
  1399. ],
  1400. "outputs": [
  1401. {
  1402. "amount": 1,
  1403. "id": "00bfa73302d12ffd",
  1404. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1405. },
  1406. {
  1407. "amount": 1,
  1408. "id": "00bfa73302d12ffd",
  1409. "B_": "03afe7c87e32d436f0957f1d70a2bca025822a84a8623e3a33aed0a167016e0ca5"
  1410. }
  1411. ]
  1412. }"#;
  1413. let invalid_swap: SwapRequest = serde_json::from_str(invalid_swap).unwrap();
  1414. assert!(
  1415. invalid_swap.verify_spending_conditions().is_err(),
  1416. "Invalid swap with mixed refunds and pubkeys shouldn't be accepted"
  1417. );
  1418. }
  1419. #[test]
  1420. fn test_sig_all_locktime_passed_with_valid_refund_key_sigs() {
  1421. // The following is a SwapRequest with locktime passed and refund keys signatures are valid
  1422. let valid_swap = r#"{
  1423. "inputs": [
  1424. {
  1425. "amount": 2,
  1426. "id": "00bfa73302d12ffd",
  1427. "secret": "[\"P2PK\",{\"nonce\":\"9ea35553beb18d553d0a53120d0175a0991ca6109370338406eed007b26eacd1\",\"data\":\"02af21e09300af92e7b48c48afdb12e22933738cfb9bba67b27c00c679aae3ec25\",\"tags\":[[\"locktime\",\"1\"],[\"refund\",\"02637c19143c58b2c58bd378400a7b82bdc91d6dedaeb803b28640ef7d28a887ac\",\"0345c7fdf7ec7c8e746cca264bf27509eb4edb9ac421f8fbfab1dec64945a4d797\"],[\"n_sigs_refund\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1428. "C": "03dd83536fbbcbb74ccb3c87147df26753fd499cc2c095f74367fff0fb459c312e",
  1429. "witness": "{\"signatures\":[\"23b58ef28cd22f3dff421121240ddd621deee83a3bc229fd67019c2e338d91e2c61577e081e1375dbab369307bba265e887857110ca3b4bd949211a0a298805f\",\"7e75948ef1513564fdcecfcbd389deac67c730f7004f8631ba90c0844d3e8c0cf470b656306877df5141f65fd3b7e85445a8452c3323ab273e6d0d44843817ed\"]}"
  1430. }
  1431. ],
  1432. "outputs": [
  1433. {
  1434. "amount": 2,
  1435. "id": "00bfa73302d12ffd",
  1436. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1437. }
  1438. ]
  1439. }"#;
  1440. let valid_swap: SwapRequest = serde_json::from_str(valid_swap).unwrap();
  1441. assert!(
  1442. valid_swap.verify_spending_conditions().is_ok(),
  1443. "Valid post-locktime swap with refund keys should be accepted"
  1444. );
  1445. }
  1446. #[test]
  1447. fn test_sig_all_htlc_and_pubkey() {
  1448. // The following is a valid `SwapRequest` with an HTLC also locked to a public key
  1449. let valid_swap = r#"{
  1450. "inputs": [
  1451. {
  1452. "amount": 2,
  1453. "id": "00bfa73302d12ffd",
  1454. "secret": "[\"HTLC\",{\"nonce\":\"d730dd70cd7ec6e687829857de8e70aab2b970712f4dbe288343eca20e63c28c\",\"data\":\"ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5\",\"tags\":[[\"pubkeys\",\"0350cda8a1d5257dbd6ba8401a9a27384b9ab699e636e986101172167799469b14\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1455. "C": "03ff6567e2e6c31db5cb7189dab2b5121930086791c93899e4eff3dda61cb57273",
  1456. "witness": "{\"preimage\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"signatures\":[\"a4c00a9ad07f9936e404494fda99a9b935c82d7c053173b304b8663124c81d4b00f64a225f5acf41043ca52b06382722bd04ded0fbeb0fcc404eed3b24778b88\"]}"
  1457. }
  1458. ],
  1459. "outputs": [
  1460. {
  1461. "amount": 2,
  1462. "id": "00bfa73302d12ffd",
  1463. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1464. }
  1465. ]
  1466. }"#;
  1467. let valid_swap: SwapRequest = serde_json::from_str(valid_swap).unwrap();
  1468. assert!(
  1469. valid_swap.verify_spending_conditions().is_ok(),
  1470. "Valid swap with htlc and pubkey should be accepted"
  1471. );
  1472. }
  1473. #[test]
  1474. fn test_sig_all_enforce_locktime_with_only_refund_signed() {
  1475. // The following is an invalid SwapRequest with an HTLC also locked to a public key, locktime and refund key. locktime is not expired but proof is signed with refund key.
  1476. let invalid_swap = r#"{
  1477. "inputs": [
  1478. {
  1479. "amount": 2,
  1480. "id": "00bfa73302d12ffd",
  1481. "secret": "[\"HTLC\",{\"nonce\":\"512c4045f12fdfd6f55059669c189e040c37c1ce2f8be104ed6aec296acce4e9\",\"data\":\"ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5\",\"tags\":[[\"pubkeys\",\"03ba83defd31c63f8841d188f0d41b5bb3af1bb3c08d0ba46f8f1d26a4d45e8cad\"],[\"locktime\",\"4854185133\"],[\"refund\",\"032f1008a79c722e93a1b4b853f85f38283f9ef74ee4c5c91293eb1cc3c5e46e34\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1482. "C": "02207abeff828146f1fc3909c74613d5605bd057f16791994b3c91f045b39a6939",
  1483. "witness": "{\"preimage\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"signatures\":[\"7816d57871bde5be2e4281065dbe5b15f641d8f1ed9437a3ae556464d6f9b8a0a2e6660337a915f2c26dce1453a416daf682b8fb593b67a0750fce071e0759b9\"]}"
  1484. }
  1485. ],
  1486. "outputs": [
  1487. {
  1488. "amount": 1,
  1489. "id": "00bfa73302d12ffd",
  1490. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1491. },
  1492. {
  1493. "amount": 1,
  1494. "id": "00bfa73302d12ffd",
  1495. "B_": "03afe7c87e32d436f0957f1d70a2bca025822a84a8623e3a33aed0a167016e0ca5"
  1496. }
  1497. ]
  1498. }"#;
  1499. let invalid_swap: SwapRequest = serde_json::from_str(invalid_swap).unwrap();
  1500. assert!(
  1501. invalid_swap.verify_spending_conditions().is_err(),
  1502. "Invalid swap with pre-locktime conditions not met shouldn't be accepted"
  1503. );
  1504. }
  1505. #[test]
  1506. fn test_sig_all_htlc_post_locktime() {
  1507. // The following is a valid SwapRequest with a multisig HTLC also locked to locktime and refund keys.
  1508. let valid_swap = r#"{
  1509. "inputs": [
  1510. {
  1511. "amount": 2,
  1512. "id": "00bfa73302d12ffd",
  1513. "secret": "[\"HTLC\",{\"nonce\":\"c9b0fabb8007c0db4bef64d5d128cdcf3c79e8bb780c3294adf4c88e96c32647\",\"data\":\"ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5\",\"tags\":[[\"pubkeys\",\"039e6ec7e922abb4162235b3a42965eb11510b07b7461f6b1a17478b1c9c64d100\"],[\"locktime\",\"1\"],[\"refund\",\"02ce1bbd2c9a4be8029c9a6435ad601c45677f5cde81f8a7f0ed535e0039d0eb6c\",\"03c43c00ff57f63cfa9e732f0520c342123e21331d0121139f1b636921eeec095f\"],[\"n_sigs_refund\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1514. "C": "0344b6f1471cf18a8cbae0e624018c816be5e3a9b04dcb7689f64173c1ae90a3a5",
  1515. "witness": "{\"preimage\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"signatures\":[\"98e21672d409cc782c720f203d8284f0af0c8713f18167499f9f101b7050c3e657fb0e57478ebd8bd561c31aa6c30f4cd20ec38c73f5755b7b4ddee693bca5a5\",\"693f40129dbf905ed9c8008081c694f72a36de354f9f4fa7a61b389cf781f62a0ae0586612fb2eb504faaf897fefb6742309186117f4743bcebcb8e350e975e2\"]}"
  1516. }
  1517. ],
  1518. "outputs": [
  1519. {
  1520. "amount": 2,
  1521. "id": "00bfa73302d12ffd",
  1522. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1523. }
  1524. ]
  1525. }"#;
  1526. let valid_swap: SwapRequest = serde_json::from_str(valid_swap).unwrap();
  1527. assert!(
  1528. valid_swap.verify_spending_conditions().is_ok(),
  1529. "Valid post-locktime swap with htlc should be accepted"
  1530. );
  1531. }
  1532. #[test]
  1533. fn test_sig_all_swap_mismatched_inputs() {
  1534. // Invalid SwapRequest - mismatched inputs with SIG_ALL
  1535. let invalid_swap = r#"{
  1536. "inputs": [
  1537. {
  1538. "amount": 1,
  1539. "id": "00bfa73302d12ffd",
  1540. "secret": "[\"P2PK\",{\"nonce\":\"e2a221fe361f19d95c5c3312ccff3ffa075b4fe37beec99de85a6ee70568385b\",\"data\":\"03dad7f9c588f4cbb55c2e1b7b802fa2bbc63a614d9e9ecdf56a8e7ee8ca65be86\",\"tags\":[[\"pubkeys\",\"025f2af63fd65ca97c3bde4070549683e72769d28def2f1cd3d63576cd9c2ffa6c\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1541. "C": "02a79c09b0605f4e7a21976b511cc7be01cdaeac54b29645258c84f2e74bff13f6",
  1542. "witness": "{\"signatures\":[\"b42c7af7e98ca4e3bba8b73702120970286196340b340c21299676dbc7b10cafaa7baeb243affc01afce3218616cf8b3f6b4baaf4414fedb31b0c6653912f769\",\"17781910e2d806cae464f8a692929ee31124c0cd7eaf1e0d94292c6cbc122da09076b649080b8de9201f87d83b99fe04e33d701817eb287d1cdd9c4d0410e625\"]}"
  1543. },
  1544. {
  1545. "amount": 2,
  1546. "id": "00bfa73302d12ffd",
  1547. "secret": "[\"P2PK\",{\"nonce\":\"973c78b5e84c0986209dc14ba57682baf38fa4c1ea60c4c5f6834779a1a13e6d\",\"data\":\"02685df03c777837bc7155bd2d0d8e98eede7e956a4cd8a9edac84532584e68e0f\",\"tags\":[[\"pubkeys\",\"025f2af63fd65ca97c3bde4070549683e72769d28def2f1cd3d63576cd9c2ffa6c\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1548. "C": "02be48c564cf6a7b4d09fbaf3a78a153a79f687ac4623e48ce1788effc3fb1e024"
  1549. }
  1550. ],
  1551. "outputs": [
  1552. {
  1553. "amount": 1,
  1554. "id": "00bfa73302d12ffd",
  1555. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1556. },
  1557. {
  1558. "amount": 1,
  1559. "id": "00bfa73302d12ffd",
  1560. "B_": "03afe7c87e32d436f0957f1d70a2bca025822a84a8623e3a33aed0a167016e0ca5"
  1561. },
  1562. {
  1563. "amount": 1,
  1564. "id": "00bfa73302d12ffd",
  1565. "B_": "02c0d4fce02a7a0f09e3f1bca952db910b17e81a7ebcbce62cd8dcfb127d21e37b"
  1566. }
  1567. ]
  1568. }"#;
  1569. let invalid_swap: SwapRequest = serde_json::from_str(invalid_swap).unwrap();
  1570. assert!(
  1571. invalid_swap.verify_spending_conditions().is_err(),
  1572. "Invalid SIG_ALL swap request should fail verification"
  1573. );
  1574. }
  1575. #[test]
  1576. fn test_sig_all_mixed_pubkeys_and_refund_pubkeys() {
  1577. // SwapRequest with mixed up signatures from pubkey and refund_pubkeys
  1578. let invalidsig_all_swap = r#"{
  1579. "inputs": [
  1580. {
  1581. "amount": 2,
  1582. "id": "00bfa73302d12ffd",
  1583. "secret": "[\"P2PK\",{\"nonce\":\"cc93775c74df53d7c97eb37f72018d166a45ce4f4c65f11c4014b19acd02bd2f\",\"data\":\"02f515ab63e973e0dadfc284bf2ef330b01aa99c3ff775d88272f9c17afa25568c\",\"tags\":[[\"pubkeys\",\"026925e5bb547a3ec6b2d9b8934e23b882f54f89b2a9f45300bf81fd1b311d9c97\"],[\"n_sigs\",\"2\"],[\"refund\",\"03c8cd46b7e6592c41df38bc54dce2555586e7adbb15cc80a02d1a05829677286d\"],[\"n_sigs_refund\",\"1\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1584. "C": "03f6d40d0ab11f4082ee7e977534a6fcd151394d647cde4ab122157e6d755410fd",
  1585. "witness": "{\"signatures\":[\"a9f61c2b7161a50839bf7f3e2e1cb9bd7bdacd2ce62c0d458a5969db44646dad409a282241b412e8b191cc7432bcfebf16ad72339a9fb966ca71c8bd971662cc\",\"aa778ec15fe9408e1989c712c823e833f33d45780b9a25555ea76004b05d495e99fd326914484f92e7e91f919ee575e79add26e9d4bbe4349d7333d7e0021af7\"]}"
  1586. }
  1587. ],
  1588. "outputs": [
  1589. {
  1590. "amount": 1,
  1591. "id": "00bfa73302d12ffd",
  1592. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1593. },
  1594. {
  1595. "amount": 1,
  1596. "id": "00bfa73302d12ffd",
  1597. "B_": "03afe7c87e32d436f0957f1d70a2bca025822a84a8623e3a33aed0a167016e0ca5"
  1598. }
  1599. ]
  1600. }"#;
  1601. let invalid_swap: SwapRequest = serde_json::from_str(invalidsig_all_swap).unwrap();
  1602. assert!(
  1603. invalid_swap.verify_spending_conditions().is_err(),
  1604. "Invalid SIG_ALL swap request should fail verification"
  1605. );
  1606. }
  1607. #[test]
  1608. fn test_sig_all_htlc_unexpired_timelock_refund_signature() {
  1609. // SwapRequest signed with refund_pubkey without expiration
  1610. let invalidsig_all_swap = r#"{
  1611. "inputs": [
  1612. {
  1613. "amount": 2,
  1614. "id": "00bfa73302d12ffd",
  1615. "secret": "[\"HTLC\",{\"nonce\":\"b6f0c59ea4084369d4196e1318477121c2451d59ae767060e083cb6846e6bbe0\",\"data\":\"ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5\",\"tags\":[[\"pubkeys\",\"0329fdfde4becf9ff871129653ff6464bb2c922fbcba442e6166a8b5849599604f\"],[\"locktime\",\"4854185133\"],[\"refund\",\"035fcf4a5393e4bdef0567aa0b8a9555edba36e5fcb283f3bbce52d86a687817d3\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1616. "C": "024fbbee3f3cc306a48841ba327435b64de20b8b172b98296a3e573c673d52562b",
  1617. "witness": "{\"preimage\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"signatures\":[\"7526819070a291f731e77acfbe9da71ddc0f748fd2a3e6c2510bc83c61daaa656df345afa3832fe7cb94352c8835a4794ad499760729c0be29417387d1fc3cd1\"]}"
  1618. }
  1619. ],
  1620. "outputs": [
  1621. {
  1622. "amount": 2,
  1623. "id": "00bfa73302d12ffd",
  1624. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1625. }
  1626. ]
  1627. }"#;
  1628. let invalid_swap: SwapRequest = serde_json::from_str(invalidsig_all_swap).unwrap();
  1629. assert!(
  1630. invalid_swap.verify_spending_conditions().is_err(),
  1631. "Invalid SIG_ALL swap request should fail verification"
  1632. );
  1633. }
  1634. // Now the Melt examples at the end of 11-test.md
  1635. #[test]
  1636. fn test_sig_all_melt() {
  1637. // Valid MeltRequest with SIG_ALL signature
  1638. // Example MeltRequest:
  1639. let valid_melt = r#"{
  1640. "quote": "cF8911fzT88aEi1d-6boZZkq5lYxbUSVs-HbJxK0",
  1641. "inputs": [
  1642. {
  1643. "amount": 2,
  1644. "id": "00bfa73302d12ffd",
  1645. "secret": "[\"P2PK\",{\"nonce\":\"bbf9edf441d17097e39f5095a3313ba24d3055ab8a32f758ff41c10d45c4f3de\",\"data\":\"029116d32e7da635c8feeb9f1f4559eb3d9b42d400f9d22a64834d89cde0eb6835\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]",
  1646. "C": "02a9d461ff36448469dccf828fa143833ae71c689886ac51b62c8d61ddaa10028b",
  1647. "witness": "{\"signatures\":[\"478224fbe715e34f78cb33451db6fcf8ab948afb8bd04ff1a952c92e562ac0f7c1cb5e61809410635be0aa94d0448f7f7959bd5762cc3802b0a00ff58b2da747\"]}"
  1648. }
  1649. ],
  1650. "outputs": [
  1651. {
  1652. "amount": 0,
  1653. "id": "00bfa73302d12ffd",
  1654. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1655. }
  1656. ]
  1657. }"#;
  1658. let valid_melt: MeltRequest<String> = serde_json::from_str(valid_melt).unwrap();
  1659. // Verify the message format
  1660. let msg_to_sign = valid_melt.sig_all_msg_to_sign();
  1661. assert_eq!(
  1662. msg_to_sign,
  1663. r#"["P2PK",{"nonce":"bbf9edf441d17097e39f5095a3313ba24d3055ab8a32f758ff41c10d45c4f3de","data":"029116d32e7da635c8feeb9f1f4559eb3d9b42d400f9d22a64834d89cde0eb6835","tags":[["sigflag","SIG_ALL"]]}]02a9d461ff36448469dccf828fa143833ae71c689886ac51b62c8d61ddaa10028b0038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39cF8911fzT88aEi1d-6boZZkq5lYxbUSVs-HbJxK0"#
  1664. );
  1665. // Verify the SHA256 hash of the message
  1666. use bitcoin::hashes::{sha256, Hash};
  1667. let msg_hash = sha256::Hash::hash(msg_to_sign.as_bytes());
  1668. assert_eq!(
  1669. msg_hash.to_string(),
  1670. "9efa1067cc7dc870f4074f695115829c3cd817a6866c3b84e9814adf3c3cf262"
  1671. );
  1672. assert!(
  1673. valid_melt.verify_spending_conditions().is_ok(),
  1674. "Valid SIG_ALL melt request should verify"
  1675. );
  1676. }
  1677. #[test]
  1678. fn test_sig_all_valid_melt() {
  1679. // The following is a valid SIG_ALL MeltRequest.
  1680. let valid_melt = r#"{
  1681. "quote": "cF8911fzT88aEi1d-6boZZkq5lYxbUSVs-HbJxK0",
  1682. "inputs": [
  1683. {
  1684. "amount": 2,
  1685. "id": "00bfa73302d12ffd",
  1686. "secret": "[\"P2PK\",{\"nonce\":\"bbf9edf441d17097e39f5095a3313ba24d3055ab8a32f758ff41c10d45c4f3de\",\"data\":\"029116d32e7da635c8feeb9f1f4559eb3d9b42d400f9d22a64834d89cde0eb6835\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]",
  1687. "C": "02a9d461ff36448469dccf828fa143833ae71c689886ac51b62c8d61ddaa10028b",
  1688. "witness": "{\"signatures\":[\"478224fbe715e34f78cb33451db6fcf8ab948afb8bd04ff1a952c92e562ac0f7c1cb5e61809410635be0aa94d0448f7f7959bd5762cc3802b0a00ff58b2da747\"]}"
  1689. }
  1690. ],
  1691. "outputs": [
  1692. {
  1693. "amount": 0,
  1694. "id": "00bfa73302d12ffd",
  1695. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1696. }
  1697. ]
  1698. }"#;
  1699. let valid_melt: MeltRequest<String> = serde_json::from_str(valid_melt).unwrap();
  1700. assert!(
  1701. valid_melt.verify_spending_conditions().is_ok(),
  1702. "Valid SIG_ALL melt request should verify"
  1703. );
  1704. }
  1705. #[test]
  1706. fn test_sig_all_valid_multisig_melt() {
  1707. // The following is a valid multi-sig SIG_ALL MeltRequest.
  1708. let valid_melt = r#"{
  1709. "quote": "Db3qEMVwFN2tf_1JxbZp29aL5cVXpSMIwpYfyOVF",
  1710. "inputs": [
  1711. {
  1712. "amount": 2,
  1713. "id": "00bfa73302d12ffd",
  1714. "secret": "[\"P2PK\",{\"nonce\":\"68d7822538740e4f9c9ebf5183ef6c4501c7a9bca4e509ce2e41e1d62e7b8a99\",\"data\":\"0394e841bd59aeadce16380df6174cb29c9fea83b0b65b226575e6d73cc5a1bd59\",\"tags\":[[\"pubkeys\",\"033d892d7ad2a7d53708b7a5a2af101cbcef69522bd368eacf55fcb4f1b0494058\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1715. "C": "03a70c42ec9d7192422c7f7a3ad017deda309fb4a2453fcf9357795ea706cc87a9",
  1716. "witness": "{\"signatures\":[\"ed739970d003f703da2f101a51767b63858f4894468cc334be04aa3befab1617a81e3eef093441afb499974152d279e59d9582a31dc68adbc17ffc22a2516086\",\"f9efe1c70eb61e7ad8bd615c50ff850410a4135ea73ba5fd8e12a734743ad045e575e9e76ea5c52c8e7908d3ad5c0eaae93337e5c11109e52848dc328d6757a2\"]}"
  1717. }
  1718. ],
  1719. "outputs": [
  1720. {
  1721. "amount": 0,
  1722. "id": "00bfa73302d12ffd",
  1723. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1724. }
  1725. ]
  1726. }"#;
  1727. let valid_melt: MeltRequest<String> = serde_json::from_str(valid_melt).unwrap();
  1728. assert!(
  1729. valid_melt.verify_spending_conditions().is_ok(),
  1730. "Valid SIG_ALL melt request should verify"
  1731. );
  1732. }
  1733. #[test]
  1734. fn test_sig_all_melt_wrong_sig() {
  1735. // Invalid MeltRequest - wrong signature for SIG_ALL
  1736. let invalid_melt = r#"{
  1737. "inputs": [{
  1738. "amount": 1,
  1739. "secret": "[\"P2PK\",{\"nonce\":\"859d4935c4907062a6297cf4e663e2835d90d97ecdd510745d32f6816323a41f\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_ALL\"]]}]",
  1740. "C": "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  1741. "id": "009a1f293253e41e",
  1742. "witness": "{\"signatures\":[\"3426df9730d365a9d18d79bed2f3e78e9172d7107c55306ac5ddd1b2d065893366cfa24ff3c874ebf1fc22360ba5888ddf6ff5dbcb9e5f2f5a1368f7afc64f15\"]}"
  1743. }],
  1744. "quote": "test_quote_123",
  1745. "outputs": null
  1746. }"#;
  1747. let invalid_melt: MeltRequest<String> = serde_json::from_str(invalid_melt).unwrap();
  1748. assert!(
  1749. invalid_melt.verify_spending_conditions().is_err(),
  1750. "Invalid SIG_ALL melt request should fail verification"
  1751. );
  1752. }
  1753. #[test]
  1754. #[ignore]
  1755. fn test_sig_all_melt_msg_to_sign() {
  1756. let multisig_melt = r#"{
  1757. "quote": "uHwJ-f6HFAC-lU2dMw0KOu6gd5S571FXQQHioYMD",
  1758. "inputs": [
  1759. {
  1760. "amount": 4,
  1761. "id": "00bfa73302d12ffd",
  1762. "secret": "[\"P2PK\",{\"nonce\":\"f5c26c928fb4433131780105eac330338bb9c0af2b2fd29fad9e4f18c4a96d84\",\"data\":\"03c4840e19277822bfeecf104dcd3f38d95b33249983ac6fed755869f23484fb2a\",\"tags\":[[\"pubkeys\",\"0256dcc53d9330e0bc6e9b3d47c26287695aba9fe55cafdde6f46ef56e09582bfb\"],[\"n_sigs\",\"1\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1763. "C": "02174667f98114abeb741f4964bdc88a3b86efde0afa38f791094c1e07e5df3beb",
  1764. "witness": "{\"signatures\":[\"abeeceba92bc7d1c514844ddb354d1e88a9776dfb55d3cdc5c289240386e401c3d983b68371ce5530e86c8fc4ff90195982a262f83fa8a5335b43e75af5f5fc7\"]}"
  1765. }
  1766. ],
  1767. "outputs": [
  1768. {
  1769. "amount": 0,
  1770. "id": "00bfa73302d12ffd",
  1771. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1772. }
  1773. ]
  1774. }"#;
  1775. let multisig_melt: MeltRequest<String> = serde_json::from_str(multisig_melt).unwrap();
  1776. assert!(
  1777. multisig_melt.verify_spending_conditions().is_ok(),
  1778. "melt request with SIG_ALL should succeed"
  1779. );
  1780. let msg_to_sign = multisig_melt.sig_all_msg_to_sign();
  1781. assert_eq!(
  1782. msg_to_sign,
  1783. r#"["P2PK",{"nonce":"f5c26c928fb4433131780105eac330338bb9c0af2b2fd29fad9e4f18c4a96d84","data":"03c4840e19277822bfeecf104dcd3f38d95b33249983ac6fed755869f23484fb2a","tags":[["pubkeys","0256dcc53d9330e0bc6e9b3d47c26287695aba9fe55cafdde6f46ef56e09582bfb"],["n_sigs","1"],["sigflag","SIG_ALL"]]}]02174667f98114abeb741f4964bdc88a3b86efde0afa38f791094c1e07e5df3beb000bfa73302d12ffd038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39uHwJ-f6HFAC-lU2dMw0KOu6gd5S571FXQQHioYMD"#
  1784. );
  1785. }
  1786. #[test]
  1787. #[ignore]
  1788. fn test_sig_all_melt_multi_sig() {
  1789. // MeltRequest with multi-sig SIG_ALL requiring 2 signatures
  1790. let multisig_melt = r#"{
  1791. "quote": "wYHbJm5S1GTL28tDHoUAwcvb-31vu5kfDhnLxV9D",
  1792. "inputs": [
  1793. {
  1794. "amount": 4,
  1795. "id": "00bfa73302d12ffd",
  1796. "secret": "[\"P2PK\",{\"nonce\":\"1705e988054354b703bc9103472cc5646ec76ed557517410186fa827c19c444d\",\"data\":\"024c8b5ec0e560f1fc77d7872ab75dd10a00af73a8ba715b81093b800849cb21fb\",\"tags\":[[\"pubkeys\",\"028d32bc906b3724724244812c450f688c548020f5d5a8c1d6cd1075650933d1a3\"],[\"n_sigs\",\"2\"],[\"sigflag\",\"SIG_ALL\"]]}]",
  1797. "C": "02f2a0ff12c4dd95f2476662f1df49e5126f09a5ea1f3ce13b985db57661953072",
  1798. "witness": "{\"signatures\":[\"a98a2616716d7813394a54ddc82234e5c47f0ddbddb98ccd1cad25236758fa235c8ae64d9fccd15efbe0ad5eba52a3df8433e9f1c05bc50defcb9161a5bd4bc4\",\"dd418cbbb23276dab8d72632ee77de730b932a3c6e8e15bc8802cef13db0b346915fe6e04e7fae03c3b5af026e25f71a24dc05b28135f0a9b69bc6c7289b6b8d\"]}"
  1799. }
  1800. ],
  1801. "outputs": [
  1802. {
  1803. "amount": 0,
  1804. "id": "00bfa73302d12ffd",
  1805. "B_": "038ec853d65ae1b79b5cdbc2774150b2cb288d6d26e12958a16fb33c32d9a86c39"
  1806. }
  1807. ]
  1808. }"#;
  1809. let multisig_melt: MeltRequest<String> = serde_json::from_str(multisig_melt).unwrap();
  1810. assert!(
  1811. multisig_melt.verify_spending_conditions().is_ok(),
  1812. "Multi-sig SIG_ALL melt request should verify with both signatures"
  1813. );
  1814. // MeltRequest with insufficient signatures for multi-sig SIG_ALL
  1815. let insufficient_sigs_melt = r#"{
  1816. "inputs": [{
  1817. "amount": 1,
  1818. "secret": "[\"P2PK\",{\"nonce\":\"859d4935c4907062a6297cf4e663e2835d90d97ecdd510745d32f6816323a41f\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_ALL\"],[\"pubkeys\",\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"02142715675faf8da1ecc4d51e0b9e539fa0d52fdd96ed60dbe99adb15d6b05ad9\"],[\"n_sigs\",\"2\"]]}]",
  1819. "C": "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  1820. "id": "009a1f293253e41e",
  1821. "witness": "{\"signatures\":[\"83564aca48c668f50d022a426ce0ed19d3a9bdcffeeaee0dc1e7ea7e98e9eff1840fcc821724f623468c94f72a8b0a7280fa9ef5a54a1b130ef3055217f467b3\"]}"
  1822. }],
  1823. "quote": "test_quote_123",
  1824. "outputs": null
  1825. }"#;
  1826. let insufficient_sigs_melt: MeltRequest<String> =
  1827. serde_json::from_str(insufficient_sigs_melt).unwrap();
  1828. assert!(
  1829. insufficient_sigs_melt.verify_spending_conditions().is_err(),
  1830. "Multi-sig SIG_ALL melt request should fail with insufficient signatures"
  1831. );
  1832. }
  1833. // Helper functions for tests
  1834. fn create_test_keys() -> (SecretKey, PublicKey) {
  1835. let secret_key =
  1836. SecretKey::from_str("99590802251e78ee1051648439eedb003dc539093a48a44e7b8f2642c909ea37")
  1837. .unwrap();
  1838. let pubkey = secret_key.public_key();
  1839. (secret_key, pubkey)
  1840. }
  1841. #[test]
  1842. fn test_sig_all_basic_signing_verification() {
  1843. let (secret_key, pubkey) = create_test_keys();
  1844. // Create basic SIG_ALL conditions
  1845. let conditions = Conditions {
  1846. sig_flag: SigFlag::SigAll,
  1847. ..Default::default()
  1848. };
  1849. let secret = create_test_secret(pubkey, conditions);
  1850. let proof1 = create_test_proof(secret.clone(), pubkey, "009a1f293253e41e");
  1851. let proof2 = create_test_proof(secret, pubkey, "009a1f293253e41f");
  1852. let blinded_msg = create_test_blinded_msg(pubkey);
  1853. // Test basic signing flow
  1854. let mut swap = SwapRequest::new(vec![proof1, proof2], vec![blinded_msg]);
  1855. assert!(
  1856. swap.verify_spending_conditions().is_err(),
  1857. "Unsigned swap should fail verification"
  1858. );
  1859. assert!(
  1860. swap.sign_sig_all(secret_key).is_ok(),
  1861. "Signing should succeed"
  1862. );
  1863. println!("{}", serde_json::to_string(&swap).unwrap());
  1864. assert!(
  1865. swap.verify_spending_conditions().is_ok(),
  1866. "Signed swap should pass verification"
  1867. );
  1868. }
  1869. #[test]
  1870. fn test_sig_all_unauthorized_key() {
  1871. let (_secret_key, pubkey) = create_test_keys();
  1872. let conditions = Conditions {
  1873. sig_flag: SigFlag::SigAll,
  1874. ..Default::default()
  1875. };
  1876. let secret = create_test_secret(pubkey, conditions);
  1877. let proof = create_test_proof(secret, pubkey, "009a1f293253e41e");
  1878. let blinded_msg = create_test_blinded_msg(pubkey);
  1879. // Create unauthorized key
  1880. let unauthorized_key =
  1881. SecretKey::from_str("0000000000000000000000000000000000000000000000000000000000000001")
  1882. .unwrap();
  1883. let mut swap = SwapRequest::new(vec![proof], vec![blinded_msg]);
  1884. // Signing should succeed (no validation)
  1885. swap.sign_sig_all(unauthorized_key).unwrap();
  1886. // Verification should fail (unauthorized signature)
  1887. assert!(
  1888. swap.verify_spending_conditions().is_err(),
  1889. "Verification should fail with unauthorized key signature"
  1890. );
  1891. }
  1892. #[test]
  1893. fn test_sig_all_mismatched_secrets() {
  1894. let (secret_key, pubkey) = create_test_keys();
  1895. let conditions = Conditions {
  1896. sig_flag: SigFlag::SigAll,
  1897. ..Default::default()
  1898. };
  1899. // Create first proof with original secret
  1900. let secret1 = create_test_secret(pubkey, conditions.clone());
  1901. // Create second proof with different secret data
  1902. let different_secret = Nut10Secret::new(
  1903. Kind::P2PK,
  1904. "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
  1905. Some(conditions),
  1906. )
  1907. .try_into()
  1908. .unwrap();
  1909. let proof1 = create_test_proof(secret1, pubkey, "009a1f293253e41e");
  1910. let proof2 = create_test_proof(different_secret, pubkey, "009a1f293253e41f");
  1911. let blinded_msg = create_test_blinded_msg(pubkey);
  1912. let mut swap = SwapRequest::new(vec![proof1, proof2], vec![blinded_msg]);
  1913. // Signing should succeed (no validation)
  1914. swap.sign_sig_all(secret_key).unwrap();
  1915. // Verification should fail (mismatched secrets)
  1916. assert!(
  1917. swap.verify_spending_conditions().is_err(),
  1918. "Verification should fail with mismatched secrets"
  1919. );
  1920. }
  1921. #[test]
  1922. fn test_sig_all_wrong_flag() {
  1923. let (secret_key, pubkey) = create_test_keys();
  1924. // Create conditions with SIG_INPUTS instead of SIG_ALL
  1925. let sig_inputs_conditions = Conditions {
  1926. sig_flag: SigFlag::SigInputs,
  1927. ..Default::default()
  1928. };
  1929. let secret = create_test_secret(pubkey, sig_inputs_conditions);
  1930. let proof = create_test_proof(secret, pubkey, "009a1f293253e41e");
  1931. let blinded_msg = create_test_blinded_msg(pubkey);
  1932. let mut swap = SwapRequest::new(vec![proof], vec![blinded_msg]);
  1933. // Signing should succeed (no validation)
  1934. swap.sign_sig_all(secret_key).unwrap();
  1935. // Verification should fail (wrong flag - has SIG_INPUTS but sign_sig_all expects SIG_ALL)
  1936. assert!(
  1937. swap.verify_spending_conditions().is_err(),
  1938. "Verification should fail with SIG_INPUTS flag when sign_sig_all was used"
  1939. );
  1940. }
  1941. #[test]
  1942. fn test_sig_all_multiple_signatures() {
  1943. let (secret_key1, pubkey1) = create_test_keys();
  1944. let secret_key2 =
  1945. SecretKey::from_str("7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f")
  1946. .unwrap();
  1947. let pubkey2 = secret_key2.public_key();
  1948. // Create conditions requiring 2 signatures
  1949. let conditions = Conditions {
  1950. num_sigs: Some(2),
  1951. sig_flag: SigFlag::SigAll,
  1952. pubkeys: Some(vec![pubkey2]),
  1953. ..Default::default()
  1954. };
  1955. let secret = create_test_secret(pubkey1, conditions);
  1956. let proof = create_test_proof(secret, pubkey1, "009a1f293253e41e");
  1957. let blinded_msg = create_test_blinded_msg(pubkey1);
  1958. let mut swap = SwapRequest::new(vec![proof], vec![blinded_msg]);
  1959. // Sign with first key
  1960. assert!(
  1961. swap.sign_sig_all(secret_key1).is_ok(),
  1962. "First signature should succeed"
  1963. );
  1964. assert!(
  1965. swap.verify_spending_conditions().is_err(),
  1966. "Single signature should not verify when two required"
  1967. );
  1968. // Sign with second key
  1969. assert!(
  1970. swap.sign_sig_all(secret_key2).is_ok(),
  1971. "Second signature should succeed"
  1972. );
  1973. assert!(
  1974. swap.verify_spending_conditions().is_ok(),
  1975. "Both signatures should verify"
  1976. );
  1977. }
  1978. }