Skip to content

Commit 77ff2d8

Browse files
committed
update to latest bitcoin master
1 parent ea7170e commit 77ff2d8

File tree

8 files changed

+60
-37
lines changed

8 files changed

+60
-37
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description = "Miniscript: a subset of Bitcoin Script designed for analysis"
77
license = "CC0-1.0"
88

99
[features]
10-
fuzztarget = ["bitcoin/fuzztarget"]
10+
fuzztarget = []
1111
compiler = []
1212
trace = []
1313
unstable = []
@@ -16,7 +16,8 @@ use-serde = ["bitcoin/use-serde", "serde"]
1616
rand = ["bitcoin/rand"]
1717

1818
[dependencies]
19-
bitcoin = "0.27"
19+
# bitcoin = "0.27"
20+
bitcoin = {git = "https://github.com/rust-bitcoin/rust-bitcoin", rev = "df7250046502cfe8b92b0a8ec8bee3d5529d32f5"}
2021

2122
[dependencies.serde]
2223
version = "1.0"

examples/verify_tx.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ fn main() {
134134

135135
// We can set the amount passed to `sighash_verify` to 0 because this is a legacy
136136
// transaction and so the amount won't actually be checked by the signature
137-
let vfyfn = interpreter.sighash_verify(&secp, &transaction, 0, 0);
137+
let vfyfn = interpreter
138+
.sighash_verify(&secp, &transaction, 0, 0)
139+
.expect("Can only fail in sighash single when corresponding output is not present");
138140
// Restrict to sighash_all just to demonstrate how to add additional filters
139141
// `&_` needed here because of https://github.com/rust-lang/rust/issues/79187
140142
let vfyfn = move |pk: &_, bitcoinsig: miniscript::BitcoinSig| {

src/descriptor/sh.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,10 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Sh<Pk> {
209209
Pk: ToPublicKey,
210210
{
211211
match self.inner {
212-
ShInner::Wsh(ref wsh) => Ok(bitcoin::Address::p2sh(&wsh.script_pubkey(), network)),
213-
ShInner::Wpkh(ref wpkh) => Ok(bitcoin::Address::p2sh(&wpkh.script_pubkey(), network)),
214-
ShInner::SortedMulti(ref smv) => Ok(bitcoin::Address::p2sh(&smv.encode(), network)),
215-
ShInner::Ms(ref ms) => Ok(bitcoin::Address::p2sh(&ms.encode(), network)),
212+
ShInner::Wsh(ref wsh) => Ok(bitcoin::Address::p2sh(&wsh.script_pubkey(), network)?),
213+
ShInner::Wpkh(ref wpkh) => Ok(bitcoin::Address::p2sh(&wpkh.script_pubkey(), network)?),
214+
ShInner::SortedMulti(ref smv) => Ok(bitcoin::Address::p2sh(&smv.encode(), network)?),
215+
ShInner::Ms(ref ms) => Ok(bitcoin::Address::p2sh(&ms.encode(), network)?),
216216
}
217217
}
218218

src/interpreter/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ pub enum Error {
7171
Secp(secp256k1::Error),
7272
/// Miniscript requires the entire top level script to be satisfied.
7373
ScriptSatisfactionError,
74+
/// Errors in signature hash calculations
75+
SighashError(bitcoin::util::sighash::Error),
7476
/// An uncompressed public key was encountered in a context where it is
7577
/// disallowed (e.g. in a Segwit script or p2wpkh output)
7678
UncompressedPubkey,
@@ -95,6 +97,13 @@ impl From<secp256k1::Error> for Error {
9597
}
9698
}
9799

100+
#[doc(hidden)]
101+
impl From<bitcoin::util::sighash::Error> for Error {
102+
fn from(e: bitcoin::util::sighash::Error) -> Error {
103+
Error::SighashError(e)
104+
}
105+
}
106+
98107
#[doc(hidden)]
99108
impl From<::Error> for Error {
100109
fn from(e: ::Error) -> Error {
@@ -152,6 +161,7 @@ impl fmt::Display for Error {
152161
}
153162
Error::ScriptSatisfactionError => f.write_str("Top level script must be satisfied"),
154163
Error::Secp(ref e) => fmt::Display::fmt(e, f),
164+
Error::SighashError(ref e) => fmt::Display::fmt(e, f),
155165
Error::UncompressedPubkey => {
156166
f.write_str("uncompressed pubkey in non-legacy descriptor")
157167
}

src/interpreter/mod.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
//!
2121
2222
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d};
23-
use bitcoin::util::bip143;
23+
use bitcoin::util::sighash;
2424
use bitcoin::{self, secp256k1};
2525
use miniscript::context::NoChecks;
2626
use miniscript::ScriptContext;
@@ -170,16 +170,16 @@ impl<'txin> Interpreter<'txin> {
170170
input_idx: usize,
171171
amount: u64,
172172
sighash_type: bitcoin::SigHashType,
173-
) -> secp256k1::Message {
173+
) -> Result<secp256k1::Message, Error> {
174+
let mut cache = sighash::SigHashCache::new(unsigned_tx);
174175
let hash = if self.is_legacy() {
175-
unsigned_tx.signature_hash(input_idx, &self.script_code, sighash_type.as_u32())
176+
cache.legacy_signature_hash(input_idx, &self.script_code, sighash_type.as_u32())?
176177
} else {
177-
let mut sighash_cache = bip143::SigHashCache::new(unsigned_tx);
178-
sighash_cache.signature_hash(input_idx, &self.script_code, amount, sighash_type)
178+
cache.segwit_signature_hash(input_idx, &self.script_code, amount, sighash_type)?
179179
};
180180

181-
secp256k1::Message::from_slice(&hash[..])
182-
.expect("cryptographically unreachable for this to fail")
181+
Ok(secp256k1::Message::from_slice(&hash[..])
182+
.expect("cryptographically unreachable for this to fail"))
183183
}
184184

185185
/// Returns a closure which can be given to the `iter` method to check all signatures
@@ -189,34 +189,34 @@ impl<'txin> Interpreter<'txin> {
189189
unsigned_tx: &'a bitcoin::Transaction,
190190
input_idx: usize,
191191
amount: u64,
192-
) -> impl Fn(&bitcoin::PublicKey, BitcoinSig) -> bool + 'a {
192+
) -> Result<impl Fn(&bitcoin::PublicKey, BitcoinSig) -> bool + 'a, Error> {
193193
// Precompute all sighash types because the borrowck doesn't like us
194194
// pulling self into the closure
195195
let sighashes = [
196-
self.sighash_message(unsigned_tx, input_idx, amount, bitcoin::SigHashType::All),
197-
self.sighash_message(unsigned_tx, input_idx, amount, bitcoin::SigHashType::None),
198-
self.sighash_message(unsigned_tx, input_idx, amount, bitcoin::SigHashType::Single),
196+
self.sighash_message(unsigned_tx, input_idx, amount, bitcoin::SigHashType::All)?,
197+
self.sighash_message(unsigned_tx, input_idx, amount, bitcoin::SigHashType::None)?,
198+
self.sighash_message(unsigned_tx, input_idx, amount, bitcoin::SigHashType::Single)?,
199199
self.sighash_message(
200200
unsigned_tx,
201201
input_idx,
202202
amount,
203203
bitcoin::SigHashType::AllPlusAnyoneCanPay,
204-
),
204+
)?,
205205
self.sighash_message(
206206
unsigned_tx,
207207
input_idx,
208208
amount,
209209
bitcoin::SigHashType::NonePlusAnyoneCanPay,
210-
),
210+
)?,
211211
self.sighash_message(
212212
unsigned_tx,
213213
input_idx,
214214
amount,
215215
bitcoin::SigHashType::SinglePlusAnyoneCanPay,
216-
),
216+
)?,
217217
];
218218

219-
move |pk: &bitcoin::PublicKey, (sig, sighash_type)| {
219+
Ok(move |pk: &bitcoin::PublicKey, (sig, sighash_type)| {
220220
// This is an awkward way to do this lookup, but it lets us do exhaustiveness
221221
// checking in case future rust-bitcoin versions add new sighash types
222222
let sighash = match sighash_type {
@@ -228,7 +228,7 @@ impl<'txin> Interpreter<'txin> {
228228
bitcoin::SigHashType::SinglePlusAnyoneCanPay => sighashes[5],
229229
};
230230
secp.verify(&sighash, &sig, &pk.key).is_ok()
231-
}
231+
})
232232
}
233233
}
234234

src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@ pub enum Error {
475475
InvalidPush(Vec<u8>),
476476
/// rust-bitcoin script error
477477
Script(script::Error),
478+
/// rust-bitcoin address error
479+
AddrError(bitcoin::util::address::Error),
478480
/// A `CHECKMULTISIG` opcode was preceded by a number > 20
479481
CmsTooManyKeys(u32),
480482
/// Encountered unprintable character in descriptor
@@ -582,6 +584,13 @@ impl From<bitcoin::secp256k1::Error> for Error {
582584
}
583585
}
584586

587+
#[doc(hidden)]
588+
impl From<bitcoin::util::address::Error> for Error {
589+
fn from(e: bitcoin::util::address::Error) -> Error {
590+
Error::AddrError(e)
591+
}
592+
}
593+
585594
fn errstr(s: &str) -> Error {
586595
Error::Unexpected(s.to_owned())
587596
}
@@ -607,6 +616,7 @@ impl fmt::Display for Error {
607616
Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
608617
Error::InvalidPush(ref push) => write!(f, "invalid push {:?}", push), // TODO hexify this
609618
Error::Script(ref e) => fmt::Display::fmt(e, f),
619+
Error::AddrError(ref e) => fmt::Display::fmt(e, f),
610620
Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
611621
Error::Unprintable(x) => write!(f, "unprintable character 0x{:02x}", x),
612622
Error::ExpectedChar(c) => write!(f, "expected {}", c),

src/psbt/finalizer.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn get_scriptpubkey(psbt: &Psbt, index: usize) -> Result<&Script, InputError> {
3535
if let Some(ref witness_utxo) = inp.witness_utxo {
3636
script_pubkey = &witness_utxo.script_pubkey;
3737
} else if let Some(ref non_witness_utxo) = inp.non_witness_utxo {
38-
let vout = psbt.global.unsigned_tx.input[index].previous_output.vout;
38+
let vout = psbt.unsigned_tx.input[index].previous_output.vout;
3939
script_pubkey = &non_witness_utxo.output[vout as usize].script_pubkey;
4040
} else {
4141
return Err(InputError::MissingUtxo);
@@ -50,7 +50,7 @@ fn get_amt(psbt: &Psbt, index: usize) -> Result<u64, InputError> {
5050
if let Some(ref witness_utxo) = inp.witness_utxo {
5151
amt = witness_utxo.value;
5252
} else if let Some(ref non_witness_utxo) = inp.non_witness_utxo {
53-
let vout = psbt.global.unsigned_tx.input[index].previous_output.vout;
53+
let vout = psbt.unsigned_tx.input[index].previous_output.vout;
5454
amt = non_witness_utxo.output[vout as usize].value;
5555
} else {
5656
return Err(InputError::MissingUtxo);
@@ -219,15 +219,17 @@ pub fn interpreter_check<C: secp256k1::Verification>(
219219
// Now look at all the satisfied constraints. If everything is filled in
220220
// corrected, there should be no errors
221221

222-
let cltv = psbt.global.unsigned_tx.lock_time;
223-
let csv = psbt.global.unsigned_tx.input[index].sequence;
222+
let cltv = psbt.unsigned_tx.lock_time;
223+
let csv = psbt.unsigned_tx.input[index].sequence;
224224
let amt = get_amt(psbt, index).map_err(|e| Error::InputError(e, index))?;
225225

226226
let mut interpreter =
227227
interpreter::Interpreter::from_txdata(spk, &script_sig, &witness, cltv, csv)
228228
.map_err(|e| Error::InputError(InputError::Interpreter(e), index))?;
229229

230-
let vfyfn = interpreter.sighash_verify(&secp, &psbt.global.unsigned_tx, index, amt);
230+
let vfyfn = interpreter
231+
.sighash_verify(&secp, &psbt.unsigned_tx, index, amt)
232+
.map_err(|e| Error::InputError(InputError::Interpreter(e), index))?;
231233
if let Some(error) = interpreter.iter(vfyfn).filter_map(Result::err).next() {
232234
return Err(Error::InputError(InputError::Interpreter(error), index));
233235
}

src/psbt/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfie
253253
}
254254

255255
fn check_after(&self, n: u32) -> bool {
256-
let locktime = self.psbt.global.unsigned_tx.lock_time;
257-
let seq = self.psbt.global.unsigned_tx.input[self.index].sequence;
256+
let locktime = self.psbt.unsigned_tx.lock_time;
257+
let seq = self.psbt.unsigned_tx.input[self.index].sequence;
258258

259259
// https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
260260
// fail if TxIn is finalized
@@ -266,14 +266,12 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfie
266266
}
267267

268268
fn check_older(&self, n: u32) -> bool {
269-
let seq = self.psbt.global.unsigned_tx.input[self.index].sequence;
269+
let seq = self.psbt.unsigned_tx.input[self.index].sequence;
270270
// https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
271271
// Disable flag set. return true
272272
if n & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
273273
true
274-
} else if self.psbt.global.unsigned_tx.version < 2
275-
|| (seq & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0)
276-
{
274+
} else if self.psbt.unsigned_tx.version < 2 || (seq & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0) {
277275
// transaction version and sequence check
278276
false
279277
} else {
@@ -321,9 +319,9 @@ fn try_vec_as_preimage32(vec: &Vec<u8>) -> Option<Preimage32> {
321319
}
322320

323321
fn sanity_check(psbt: &Psbt) -> Result<(), Error> {
324-
if psbt.global.unsigned_tx.input.len() != psbt.inputs.len() {
322+
if psbt.unsigned_tx.input.len() != psbt.inputs.len() {
325323
return Err(Error::WrongInputCount {
326-
in_tx: psbt.global.unsigned_tx.input.len(),
324+
in_tx: psbt.unsigned_tx.input.len(),
327325
in_map: psbt.inputs.len(),
328326
}
329327
.into());
@@ -343,7 +341,7 @@ pub fn extract<C: secp256k1::Verification>(
343341
) -> Result<bitcoin::Transaction, Error> {
344342
sanity_check(psbt)?;
345343

346-
let mut ret = psbt.global.unsigned_tx.clone();
344+
let mut ret = psbt.unsigned_tx.clone();
347345
for (n, input) in psbt.inputs.iter().enumerate() {
348346
if input.final_script_sig.is_none() && input.final_script_witness.is_none() {
349347
return Err(Error::InputError(InputError::MissingWitness, n));

0 commit comments

Comments
 (0)