diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index c73a7bd4e..dfee0fb35 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -313,7 +313,10 @@ where where T: Translator, { - self.real_translate_pk(translate) + let ms = self.real_translate_pk(translate)?; + ms.ext_check(&ExtParams::sane()) + .map_err(|e| TranslateErr::OuterError(Error::AnalysisError(e)))?; + Ok(ms) } } @@ -490,7 +493,10 @@ mod tests { use crate::policy::Liftable; use crate::prelude::*; use crate::test_utils::{StrKeyTranslator, StrXOnlyKeyTranslator}; - use crate::{hex_script, ExtParams, Satisfier, ToPublicKey, TranslatePk}; + use crate::{ + hex_script, AnalysisError, Error, ExtParams, Satisfier, ToPublicKey, TranslateErr, + TranslatePk, + }; type Segwitv0Script = Miniscript; type Tapscript = Miniscript; @@ -1142,4 +1148,36 @@ mod tests { t.pk_map.insert(String::from("A"), uncompressed); ms.translate_pk(&mut t).unwrap_err(); } + + #[test] + fn translate_test_duplicate() { + let ms = Miniscript::::from_str("and_b(pk(A),a:pk(B))").unwrap(); + let mut t = StrKeyTranslator::new(); + let key = bitcoin::PublicKey::from_str( + "0238e6a8035e67d46f2a350f748a9c2dd45ba467f12432e5f9371ca91fb9831086", + ) + .unwrap(); + { + t.pk_map.insert(String::from("A"), key); + t.pk_map.insert(String::from("B"), key); + let err = ms.translate_pk(&mut t).unwrap_err(); + if let TranslateErr::OuterError(Error::AnalysisError(AnalysisError::RepeatedPubkeys)) = + err + { + // pass + } else { + panic!("Unexpected error"); + } + } + // Test that regular translation works if A and B are different keys + { + let key2 = bitcoin::PublicKey::from_str( + "03a8e6a8035e67d46f2a350f748a9c2dd45ba467f12432e5f9371ca91fb9831086", + ) + .unwrap(); // insecure complement of above key + t.pk_map.insert(String::from("A"), key); + t.pk_map.insert(String::from("B"), key2); + ms.translate_pk(&mut t).unwrap(); + } + } }