Skip to content

Commit c17965a

Browse files
committed
Add method to convert expr_raw_pkh into pkh
The commit 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. Signed-off-by: Harshil Jani <[email protected]>
1 parent c9118b3 commit c17965a

File tree

3 files changed

+96
-3
lines changed

3 files changed

+96
-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: &HashMap<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: &HashMap<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: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
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;
1415
use bitcoin::taproot::LeafVersion;
1516
use bitcoin::{PublicKey, Script, ScriptBuf, TxOut, Witness};
17+
use std::collections::HashMap;
1618

1719
use super::{sanity_check, Error, InputError, Psbt, PsbtInputSatisfier};
1820
use crate::prelude::*;
@@ -122,6 +124,22 @@ pub(super) fn prevouts(psbt: &Psbt) -> Result<Vec<&bitcoin::TxOut>, super::Error
122124
// we want to move the script is probably already created
123125
// and we want to satisfy it in any way possible.
124126
fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, InputError> {
127+
// Create a HashMap <Hash(Pk),Pk>
128+
let mut hash_map: HashMap<hash160::Hash, PublicKey> = HashMap::new();
129+
let psbt_inputs = &psbt.inputs;
130+
for psbt_input in psbt_inputs {
131+
// Use BIP32 Derviation to get set of all possible keys.
132+
let public_keys = psbt_input.bip32_derivation.keys();
133+
for key in public_keys {
134+
// Convert bitcoin::secp256k1::PublicKey into just bitcoin::PublicKey
135+
let bitcoin_key = bitcoin::PublicKey::new(*key);
136+
// Convert PubKeyHash into Hash::hash160
137+
let hash = bitcoin_key.pubkey_hash().to_raw_hash();
138+
// Insert pair in HashMap
139+
hash_map.insert(hash, bitcoin_key);
140+
}
141+
}
142+
125143
// Figure out Scriptpubkey
126144
let script_pubkey = get_scriptpubkey(psbt, index)?;
127145
let inp = &psbt.inputs[index];
@@ -178,7 +196,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
178196
witness_script,
179197
&ExtParams::allow_all(),
180198
)?;
181-
Ok(Descriptor::new_wsh(ms)?)
199+
Ok(Descriptor::new_wsh(ms.substitute_raw_pkh(&hash_map))?)
182200
} else {
183201
Err(InputError::MissingWitnessScript)
184202
}
@@ -205,7 +223,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
205223
witness_script,
206224
&ExtParams::allow_all(),
207225
)?;
208-
Ok(Descriptor::new_sh_wsh(ms)?)
226+
Ok(Descriptor::new_sh_wsh(ms.substitute_raw_pkh(&hash_map))?)
209227
} else {
210228
Err(InputError::MissingWitnessScript)
211229
}
@@ -249,7 +267,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
249267
&script_pubkey,
250268
&ExtParams::allow_all(),
251269
)?;
252-
Ok(Descriptor::new_bare(ms)?)
270+
Ok(Descriptor::new_bare(ms.substitute_raw_pkh(&hash_map))?)
253271
}
254272
}
255273

0 commit comments

Comments
 (0)