Skip to content

Commit

Permalink
Merge pull request #26 from tcharding/08-07-upgrade-bitcoin
Browse files Browse the repository at this point in the history
Upgrade to latest `bitcoin` version
  • Loading branch information
tcharding authored Aug 22, 2024
2 parents 5092155 + 4b7f974 commit 7c57502
Show file tree
Hide file tree
Showing 34 changed files with 496 additions and 2,320 deletions.
20 changes: 9 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,30 @@ rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["std"]
std = ["bitcoin/std"]
no-std = ["bitcoin/no-std", "core2"]
std = ["bitcoin/std", "bitcoin-internals/std"]
rand = ["bitcoin/rand"]
rand-std = ["bitcoin/rand-std"]
serde = ["actual-serde", "bitcoin/serde"]
serde = ["actual-serde", "bitcoin/serde", "bitcoin-internals/serde"]
base64 = ["bitcoin/base64"]

miniscript-std = ["std", "miniscript/std"]
miniscript-no-std = ["no-std", "miniscript/no-std"]
miniscript-no-std = ["miniscript/no-std"]

[dependencies]
bitcoin = { version = "0.31.0", default-features = false }
bitcoin = { version = "0.32.2", default-features = false }
bitcoin-internals = { version = "0.3.0", features = ["alloc"] }

# Do not use this feature, use "miniscript-std" or "miniscript-no-std" instead.
miniscript = { version = "11.0.0", default-features = false, optional = true }
# Do NOT use this feature! Use one of the `miniscript-` features instead.
miniscript = { version = "12.2.0", default-features = false, optional = true }
# Do NOT use this as a feature! Use the `serde` feature instead.
actual-serde = { package = "serde", version = "1.0.103", default-features = false, features = [ "derive", "alloc" ], optional = true }
# There is no reason to use this dependency directly, it is activated by the "no-std" feature.
core2 = { version = "0.3.2", default-features = false, features = ["alloc"], optional = true }

[dev-dependencies]
anyhow = "1"
serde_json = "1.0.0"
serde_test = "1.0.19"
serde_derive = "1.0.103"
bincode = "1.3.1"
secp256k1 = { version = "0.28", features = ["rand-std", "global-context"] }
secp256k1 = { version = "0.29", features = ["rand-std", "global-context"] }

[[example]]
name = "v0"
Expand Down
11 changes: 4 additions & 7 deletions contrib/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,18 @@ cargo run --example v2-separate-creator-constructor
if [ "$DO_NO_STD" = true ]
then
# Build no_std, to make sure that cfg(test) doesn't hide any issues
cargo build --no-default-features --features="no-std"

# Build std + no_std, to make sure they are not incompatible
cargo build --features="no-std"
cargo build --no-default-features

# Test no_std
cargo test --no-default-features --features="no-std"
cargo test --no-default-features

# Build all features
cargo build --no-default-features --features="no-std $FEATURES"
cargo build --no-default-features --features="$FEATURES"

# Build specific features
for feature in ${FEATURES}
do
cargo build --no-default-features --features="no-std $feature"
cargo build --no-default-features --features="$feature"
done
fi

Expand Down
9 changes: 5 additions & 4 deletions examples/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use psbt_v2::bitcoin::locktime::absolute;
use psbt_v2::bitcoin::opcodes::all::OP_CHECKMULTISIG;
use psbt_v2::bitcoin::secp256k1::{self, rand, SECP256K1};
use psbt_v2::bitcoin::{
script, transaction, Address, Amount, Network, OutPoint, PublicKey, ScriptBuf, Sequence,
Transaction, TxIn, TxOut, Txid, Witness,
script, transaction, Address, Amount, CompressedPublicKey, Network, OutPoint, PublicKey,
ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
};
use psbt_v2::v0::{self, Psbt};

Expand Down Expand Up @@ -126,8 +126,9 @@ impl Alice {
let out = OutPoint { txid: Txid::all_zeros(), vout: 0 };

// The usual caveat about reusing addresses applies here, this is just an example.
let address =
Address::p2wpkh(&self.public_key(), Network::Bitcoin).expect("uncompressed key");
let compressed =
CompressedPublicKey::try_from(self.public_key()).expect("uncompressed key");
let address = Address::p2wpkh(&compressed, Network::Bitcoin);

// This is a made up value, it is supposed to represent the outpoints value minus the value
// contributed to the multisig.
Expand Down
10 changes: 6 additions & 4 deletions examples/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use psbt_v2::bitcoin::locktime::absolute;
use psbt_v2::bitcoin::opcodes::all::OP_CHECKMULTISIG;
use psbt_v2::bitcoin::secp256k1::{self, SECP256K1};
use psbt_v2::bitcoin::{
script, Address, Amount, Network, OutPoint, PublicKey, ScriptBuf, Sequence, TxOut, Txid,
script, Address, Amount, CompressedPublicKey, Network, OutPoint, PublicKey, ScriptBuf,
Sequence, TxOut, Txid,
};
use psbt_v2::v2::{
self, Constructor, InputBuilder, Modifiable, Output, OutputBuilder, Psbt, Signer, Updater,
Expand Down Expand Up @@ -147,8 +148,9 @@ impl Alice {
let out = OutPoint { txid: Txid::all_zeros(), vout: 0 };

// The usual caveat about reusing addresses applies here, this is just an example.
let address = Address::p2wpkh(&self.multisig_public_key()?, Network::Bitcoin)
.expect("uncompressed key");
let compressed =
CompressedPublicKey::try_from(self.multisig_public_key()?).expect("uncompressed key");
let address = Address::p2wpkh(&compressed, Network::Bitcoin);

// This is a made up value, it is supposed to represent the outpoints value minus the value
// contributed to the multisig.
Expand Down Expand Up @@ -250,7 +252,7 @@ impl Entity {
let path = DerivationPath::from_str(derivation_path)?;
let xpriv = self.master.derive_priv(SECP256K1, &path)?;
let pk = Xpub::from_priv(SECP256K1, &xpriv);
Ok(pk.to_pub())
Ok(pk.to_pub().into())
}

/// Returns a dummy utxo that we can spend.
Expand Down
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ test:
lint:
cargo clippy --all --all-targets --all-features -- --deny warnings

# Run the formatter
fmt:
cargo +nightly fmt --all

# Check the formatting
format:
cargo +nightly fmt --all --check
2 changes: 1 addition & 1 deletion rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ color = "Auto"
unstable_features = false
disable_all_formatting = false
skip_children = false
hide_parse_errors = false
show_parse_errors = true
error_on_line_overflow = false
error_on_unformatted = false
emit_mode = "Files"
Expand Down
12 changes: 1 addition & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,9 @@
// Coding conventions
#![warn(missing_docs)]

#[cfg(not(any(feature = "std", feature = "no-std")))]
compile_error!("at least one of the `std` or `no-std` features must be enabled");

#[macro_use]
extern crate alloc;

#[cfg(not(feature = "std"))]
extern crate core2;

#[cfg(feature = "serde")]
#[macro_use]
extern crate actual_serde as serde;
Expand All @@ -48,11 +42,7 @@ pub mod v0;
pub mod v2;
mod version;

#[cfg(feature = "std")]
use std::io;

#[cfg(not(feature = "std"))]
use core2::io;
use bitcoin::io;

#[rustfmt::skip] // Keep pubic re-exports separate
#[doc(inline)]
Expand Down
33 changes: 11 additions & 22 deletions src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ use bitcoin::consensus::encode::{
};
use bitcoin::hex::DisplayHex;

use crate::io::{self, BufRead, Write};
use crate::prelude::*;
use crate::serialize;
use crate::serialize::{Deserialize, Serialize};
use crate::{io, serialize};

/// A PSBT key-value pair in its raw byte form.
///
Expand All @@ -39,7 +40,7 @@ pub struct Pair {
}

impl Pair {
pub(crate) fn decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, serialize::Error> {
pub(crate) fn decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, serialize::Error> {
Ok(Pair { key: Key::decode(r)?, value: Decodable::consensus_decode(r)? })
}
}
Expand Down Expand Up @@ -80,13 +81,12 @@ pub struct Key {
/// The `keytype` of this PSBT map key (`keytype`).
pub type_value: u8,
/// The `keydata` itself in raw byte form.
// TODO: Consider renaming to `data`.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))]
pub key: Vec<u8>,
}

impl Key {
pub(crate) fn decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, serialize::Error> {
pub(crate) fn decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, serialize::Error> {
let VarInt(byte_size): VarInt = Decodable::consensus_decode(r)?;

if byte_size == 0 {
Expand Down Expand Up @@ -186,7 +186,7 @@ impl<Subtype> Encodable for ProprietaryKey<Subtype>
where
Subtype: Copy + From<u8> + Into<u8>,
{
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
let mut len = self.prefix.consensus_encode(w)? + 1;
w.emit_u8(self.subtype.into())?;
w.write_all(&self.key)?;
Expand All @@ -199,26 +199,15 @@ impl<Subtype> Decodable for ProprietaryKey<Subtype>
where
Subtype: Copy + From<u8> + Into<u8>,
{
fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, consensus::Error> {
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, consensus::Error> {
let prefix = Vec::<u8>::consensus_decode(r)?;
let subtype = Subtype::from(r.read_u8()?);
let key = read_to_end(r)?;

Ok(ProprietaryKey { prefix, subtype, key })
}
}
// The limit is a DOS protection mechanism the exact value is not
// important, 1024 bytes is bigger than any key should be.
let mut key = vec![];
let _ = r.read_to_limit(&mut key, 1024)?;

// core2 doesn't have read_to_end
pub(crate) fn read_to_end<D: io::Read>(mut d: D) -> Result<Vec<u8>, io::Error> {
let mut result = vec![];
let mut buf = [0u8; 64];
loop {
match d.read(&mut buf) {
Ok(0) => break,
Ok(n) => result.extend_from_slice(&buf[0..n]),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
};
Ok(ProprietaryKey { prefix, subtype, key })
}
Ok(result)
}
8 changes: 4 additions & 4 deletions src/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ pub enum Error {
/// Serialization error in bitcoin consensus-encoded structures
ConsensusEncoding(consensus::encode::Error),
/// Parsing error indicating invalid public keys
InvalidPublicKey(bitcoin::key::Error),
InvalidPublicKey(bitcoin::key::FromSliceError),
/// Parsing error indicating invalid secp256k1 public keys
InvalidSecp256k1PublicKey(secp256k1::Error),
/// Parsing error indicating invalid xonly public keys
Expand All @@ -410,7 +410,7 @@ pub enum Error {
/// PSBT data is not consumed entirely
PartialDataConsumption,
/// Couldn't converting parsed u32 to a lock time.
LockTime(absolute::Error),
LockTime(absolute::ConversionError),
/// Unsupported PSBT version.
UnsupportedVersion(version::UnsupportedVersionError),
}
Expand Down Expand Up @@ -480,8 +480,8 @@ impl From<consensus::encode::Error> for Error {
fn from(e: consensus::encode::Error) -> Self { Self::ConsensusEncoding(e) }
}

impl From<absolute::Error> for Error {
fn from(e: absolute::Error) -> Self { Self::LockTime(e) }
impl From<absolute::ConversionError> for Error {
fn from(e: absolute::ConversionError) -> Self { Self::LockTime(e) }
}

impl From<version::UnsupportedVersionError> for Error {
Expand Down
6 changes: 3 additions & 3 deletions src/v0/bitcoin/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub enum Error {
/// Integer overflow in fee calculation
FeeOverflow,
/// Parsing error indicating invalid public keys
InvalidPublicKey(bitcoin::key::Error),
InvalidPublicKey(bitcoin::key::FromSliceError),
/// Parsing error indicating invalid secp256k1 public keys
InvalidSecp256k1PublicKey(secp256k1::Error),
/// Parsing error indicating invalid xonly public keys
Expand Down Expand Up @@ -133,8 +133,8 @@ impl fmt::Display for Error {
UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(
f,
"different unsigned transaction: expected {}, actual {}",
e.txid(),
a.txid()
e.compute_txid(),
a.compute_txid()
),
NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht),
InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e),
Expand Down
10 changes: 5 additions & 5 deletions src/v0/bitcoin/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ macro_rules! impl_psbt_de_serialize {
macro_rules! impl_psbt_deserialize {
($thing:ty) => {
impl $crate::v0::bitcoin::serialize::Deserialize for $thing {
fn deserialize(bytes: &[u8]) -> Result<Self, $crate::v0::bitcoin::Error> {
fn deserialize(bytes: &[u8]) -> core::result::Result<Self, $crate::v0::bitcoin::Error> {
$crate::bitcoin::consensus::deserialize(&bytes[..])
.map_err(|e| $crate::v0::bitcoin::Error::from(e))
}
Expand Down Expand Up @@ -48,7 +48,7 @@ macro_rules! impl_psbtmap_serialize {
macro_rules! impl_psbtmap_deserialize {
($thing:ty) => {
impl $crate::v0::bitcoin::serialize::Deserialize for $thing {
fn deserialize(bytes: &[u8]) -> Result<Self, $crate::v0::bitcoin::Error> {
fn deserialize(bytes: &[u8]) -> core::result::Result<Self, $crate::v0::bitcoin::Error> {
let mut decoder = bytes;
Self::decode(&mut decoder)
}
Expand All @@ -59,9 +59,9 @@ macro_rules! impl_psbtmap_deserialize {
macro_rules! impl_psbtmap_decoding {
($thing:ty) => {
impl $thing {
pub(crate) fn decode<R: $crate::io::Read + ?Sized>(
pub(crate) fn decode<R: $crate::io::BufRead + ?Sized>(
r: &mut R,
) -> Result<Self, $crate::v0::bitcoin::Error> {
) -> core::result::Result<Self, $crate::v0::bitcoin::Error> {
let mut rv: Self = core::default::Default::default();

loop {
Expand Down Expand Up @@ -151,7 +151,7 @@ macro_rules! impl_psbt_hash_de_serialize {
macro_rules! impl_psbt_hash_deserialize {
($hash_type:ty) => {
impl $crate::v0::bitcoin::serialize::Deserialize for $hash_type {
fn deserialize(bytes: &[u8]) -> Result<Self, $crate::v0::bitcoin::Error> {
fn deserialize(bytes: &[u8]) -> core::result::Result<Self, $crate::v0::bitcoin::Error> {
<$hash_type>::from_slice(&bytes[..])
.map_err(|e| $crate::v0::bitcoin::Error::from(e))
}
Expand Down
4 changes: 2 additions & 2 deletions src/v0/bitcoin/map/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bitcoin::blockdata::transaction::Transaction;
use bitcoin::consensus::encode::MAX_VEC_SIZE;
use bitcoin::consensus::{encode, Decodable};

use crate::io::{self, Cursor, Read};
use crate::io::{BufRead, Cursor, Read};
use crate::prelude::*;
use crate::v0::bitcoin::map::Map;
use crate::v0::bitcoin::{raw, Error, Psbt};
Expand Down Expand Up @@ -83,7 +83,7 @@ impl Map for Psbt {
}

impl Psbt {
pub(crate) fn decode_global<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, Error> {
pub(crate) fn decode_global<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, Error> {
let mut r = r.take(MAX_VEC_SIZE as u64);
let mut tx: Option<Transaction> = None;
let mut version: Option<u32> = None;
Expand Down
5 changes: 1 addition & 4 deletions src/v0/bitcoin/map/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ pub struct Input {
/// The finalized, fully-constructed scriptWitness with signatures and any
/// other scripts necessary for this input to pass validation.
pub final_script_witness: Option<Witness>,
/// TODO: Proof of reserves commitment
/// RIPEMD160 hash to preimage map.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
Expand Down Expand Up @@ -159,9 +158,7 @@ impl Input {
/// # Errors
///
/// If the `sighash_type` field is set to a invalid Taproot sighash value.
pub fn taproot_hash_ty(
&self,
) -> Result<TapSighashType, crate::sighash_type::InvalidSighashTypeError> {
pub fn taproot_hash_ty(&self) -> Result<TapSighashType, InvalidSighashTypeError> {
self.sighash_type
.map(|sighash_type| sighash_type.taproot_hash_ty())
.unwrap_or(Ok(TapSighashType::Default))
Expand Down
Loading

0 comments on commit 7c57502

Please sign in to comment.