Skip to content

Commit a3327ba

Browse files
committed
Merge #557: Add method to convert expr_raw_pkh into pkh
2f3e457 Using BTreeMap in place of HashMap (Harshil Jani) c17965a Add method to convert expr_raw_pkh into pkh (Harshil Jani) Pull request description: The PR adds up the method to convert the expr_raw_pkh into pkh by looking at the available keys and their hases being stored inside of the Hashmap of PSBT Input. If the key is found corresponding to given hash, It will update to pkh. To-Do : - [ ] Write a test case. - [ ] Make it work for taproot. ACKs for top commit: sanket1729: utACK 2f3e457. Thanks for the contribution Tree-SHA512: c98d7dfe0055e01f7ff3b0c23a73faa79136aa1d446f2b1e035931c1d256712668d4a150674dd35448682dd4c91db6ea426557c48ec006f6335af796ddb8a4f4
2 parents c9118b3 + 2f3e457 commit a3327ba

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

src/miniscript/astelem.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,75 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
179179
};
180180
Ok(frag)
181181
}
182+
183+
/// Substitutes raw public keys hashes with the public keys as provided by map.
184+
pub fn substitute_raw_pkh(&self, pk_map: &BTreeMap<hash160::Hash, Pk>) -> Terminal<Pk, Ctx> {
185+
match self {
186+
Terminal::RawPkH(ref p) => match pk_map.get(p) {
187+
Some(pk) => Terminal::PkH(pk.clone()).into(),
188+
None => Terminal::RawPkH(*p).into(),
189+
},
190+
Terminal::PkK(..)
191+
| Terminal::PkH(..)
192+
| Terminal::Multi(..)
193+
| Terminal::MultiA(..)
194+
| Terminal::After(..)
195+
| Terminal::Older(..)
196+
| Terminal::Sha256(..)
197+
| Terminal::Hash256(..)
198+
| Terminal::Ripemd160(..)
199+
| Terminal::Hash160(..)
200+
| Terminal::True
201+
| Terminal::False => self.clone().into(),
202+
Terminal::Alt(ref sub) => Terminal::Alt(Arc::new(sub.substitute_raw_pkh(pk_map))),
203+
Terminal::Swap(ref sub) => Terminal::Swap(Arc::new(sub.substitute_raw_pkh(pk_map))),
204+
Terminal::Check(ref sub) => Terminal::Check(Arc::new(sub.substitute_raw_pkh(pk_map))),
205+
Terminal::DupIf(ref sub) => Terminal::DupIf(Arc::new(sub.substitute_raw_pkh(pk_map))),
206+
Terminal::Verify(ref sub) => Terminal::Verify(Arc::new(sub.substitute_raw_pkh(pk_map))),
207+
Terminal::NonZero(ref sub) => {
208+
Terminal::NonZero(Arc::new(sub.substitute_raw_pkh(pk_map)))
209+
}
210+
Terminal::ZeroNotEqual(ref sub) => {
211+
Terminal::ZeroNotEqual(Arc::new(sub.substitute_raw_pkh(pk_map)))
212+
}
213+
Terminal::AndV(ref left, ref right) => Terminal::AndV(
214+
Arc::new(left.substitute_raw_pkh(pk_map)),
215+
Arc::new(right.substitute_raw_pkh(pk_map)),
216+
),
217+
Terminal::AndB(ref left, ref right) => Terminal::AndB(
218+
Arc::new(left.substitute_raw_pkh(pk_map)),
219+
Arc::new(right.substitute_raw_pkh(pk_map)),
220+
),
221+
Terminal::AndOr(ref a, ref b, ref c) => Terminal::AndOr(
222+
Arc::new(a.substitute_raw_pkh(pk_map)),
223+
Arc::new(b.substitute_raw_pkh(pk_map)),
224+
Arc::new(c.substitute_raw_pkh(pk_map)),
225+
),
226+
Terminal::OrB(ref left, ref right) => Terminal::OrB(
227+
Arc::new(left.substitute_raw_pkh(pk_map)),
228+
Arc::new(right.substitute_raw_pkh(pk_map)),
229+
),
230+
Terminal::OrD(ref left, ref right) => Terminal::OrD(
231+
Arc::new(left.substitute_raw_pkh(pk_map)),
232+
Arc::new(right.substitute_raw_pkh(pk_map)),
233+
),
234+
Terminal::OrC(ref left, ref right) => Terminal::OrC(
235+
Arc::new(left.substitute_raw_pkh(pk_map)),
236+
Arc::new(right.substitute_raw_pkh(pk_map)),
237+
),
238+
Terminal::OrI(ref left, ref right) => Terminal::OrI(
239+
Arc::new(left.substitute_raw_pkh(pk_map)),
240+
Arc::new(right.substitute_raw_pkh(pk_map)),
241+
),
242+
Terminal::Thresh(k, ref subs) => {
243+
let subs: Vec<Arc<Miniscript<_, _>>> = subs
244+
.iter()
245+
.map(|s| Arc::new(s.substitute_raw_pkh(pk_map)))
246+
.collect();
247+
Terminal::Thresh(*k, subs)
248+
}
249+
}
250+
}
182251
}
183252

184253
impl<Pk: MiniscriptKey, Ctx: ScriptContext> ForEachKey<Pk> for Terminal<Pk, Ctx> {

src/miniscript/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use core::marker::PhantomData;
1717
use core::{fmt, hash, str};
1818

19+
use bitcoin::hashes::hash160;
1920
use bitcoin::script;
2021
use bitcoin::taproot::{LeafVersion, TapLeafHash};
2122

@@ -334,6 +335,11 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
334335
let inner = self.node.real_translate_pk(t)?;
335336
Miniscript::from_ast(inner).map_err(TranslateErr::OuterError)
336337
}
338+
339+
/// Substitutes raw public keys hashes with the public keys as provided by map.
340+
pub fn substitute_raw_pkh(&self, pk_map: &BTreeMap<hash160::Hash, Pk>) -> Miniscript<Pk, Ctx> {
341+
Miniscript::from_ast(self.node.substitute_raw_pkh(pk_map)).expect("type check failed")
342+
}
337343
}
338344

339345
impl_block_str!(

src/psbt/finalizer.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! `https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki`
99
//!
1010
11+
use bitcoin::hashes::hash160;
1112
use bitcoin::key::XOnlyPublicKey;
1213
use bitcoin::secp256k1::{self, Secp256k1};
1314
use bitcoin::sighash::Prevouts;
@@ -122,6 +123,22 @@ pub(super) fn prevouts(psbt: &Psbt) -> Result<Vec<&bitcoin::TxOut>, super::Error
122123
// we want to move the script is probably already created
123124
// and we want to satisfy it in any way possible.
124125
fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, InputError> {
126+
// Create a HashMap <Hash(Pk),Pk>
127+
let mut hash_map: BTreeMap<hash160::Hash, PublicKey> = BTreeMap::new();
128+
let psbt_inputs = &psbt.inputs;
129+
for psbt_input in psbt_inputs {
130+
// Use BIP32 Derviation to get set of all possible keys.
131+
let public_keys = psbt_input.bip32_derivation.keys();
132+
for key in public_keys {
133+
// Convert bitcoin::secp256k1::PublicKey into just bitcoin::PublicKey
134+
let bitcoin_key = bitcoin::PublicKey::new(*key);
135+
// Convert PubKeyHash into Hash::hash160
136+
let hash = bitcoin_key.pubkey_hash().to_raw_hash();
137+
// Insert pair in HashMap
138+
hash_map.insert(hash, bitcoin_key);
139+
}
140+
}
141+
125142
// Figure out Scriptpubkey
126143
let script_pubkey = get_scriptpubkey(psbt, index)?;
127144
let inp = &psbt.inputs[index];
@@ -178,7 +195,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
178195
witness_script,
179196
&ExtParams::allow_all(),
180197
)?;
181-
Ok(Descriptor::new_wsh(ms)?)
198+
Ok(Descriptor::new_wsh(ms.substitute_raw_pkh(&hash_map))?)
182199
} else {
183200
Err(InputError::MissingWitnessScript)
184201
}
@@ -205,7 +222,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
205222
witness_script,
206223
&ExtParams::allow_all(),
207224
)?;
208-
Ok(Descriptor::new_sh_wsh(ms)?)
225+
Ok(Descriptor::new_sh_wsh(ms.substitute_raw_pkh(&hash_map))?)
209226
} else {
210227
Err(InputError::MissingWitnessScript)
211228
}
@@ -249,7 +266,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
249266
&script_pubkey,
250267
&ExtParams::allow_all(),
251268
)?;
252-
Ok(Descriptor::new_bare(ms)?)
269+
Ok(Descriptor::new_bare(ms.substitute_raw_pkh(&hash_map))?)
253270
}
254271
}
255272

0 commit comments

Comments
 (0)