Skip to content

Commit

Permalink
Merge #209: upgrade to bitcoin 0.32
Browse files Browse the repository at this point in the history
f889525 improve logging on error (Riccardo Casatta)
802c006 upgrade bitcoin 0.31 -> 0.32, fix test env vars (Riccardo Casatta)

Pull request description:

  #208

  ```
      fn consensus_encode<W: bitcoin::io::Write + ?Sized>(&self, e: W) -> Result<usize, crate::encode::Error> {}
      fn consensus_decode<R: bitcoin::io::BufRead + ?Sized>(reader: &mut R) -> Result<Self, crate::encode::Error> {}
  ```

  We went for not depending on bitcoin::Encodable instead

ACKs for top commit:
  apoelstra:
    ACK f889525 successfully ran local tests

Tree-SHA512: 23fbf597c7adad52c40f1c26b2d0cad6755a0ff8f9da3ee498d2dd80856b24f557f2f7bf504712a6d25e358d5417fc5f7c467122470d9087f93f1e7d260e5539
  • Loading branch information
apoelstra committed Aug 26, 2024
2 parents ea70b14 + f889525 commit 85604b0
Show file tree
Hide file tree
Showing 12 changed files with 56 additions and 87 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ json-contract = ["serde_json"]
base64 = ["bitcoin/base64"]

[dependencies]
bitcoin = "0.31.0"
secp256k1-zkp = { version = "0.10.0", features = ["global-context", "hashes"] }
bech32 = "0.11.0"
bitcoin = "0.32.2"
secp256k1-zkp = { version = "0.11.0", features = ["global-context", "hashes"] }

# Used for ContractHash::from_json_contract.
serde_json = { version = "1.0", optional = true }
Expand Down
5 changes: 5 additions & 0 deletions contrib/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ fi
if [ "$DO_INTEGRATION" = true ]
then
(
BITCOIND_EXE_DEFAULT="$(git rev-parse --show-toplevel)/elementsd-tests/bin/bitcoind"
ELEMENTSD_EXE_DEFAULT="$(git rev-parse --show-toplevel)/elementsd-tests/bin/elementsd"

cd elementsd-tests
BITCOIND_EXE=${BITCOIND_EXE:=${BITCOIND_EXE_DEFAULT}} \
ELEMENTSD_EXE=${ELEMENTSD_EXE:=${ELEMENTSD_EXE_DEFAULT}} \
cargo test
cd ..
)
Expand Down
4 changes: 2 additions & 2 deletions elementsd-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bitcoin = "0.31.0"
bitcoin = "0.32.2"
elements = {path = "../", features = ["base64"]}
elementsd = "0.9.0"
elementsd = "0.11.0"
rand = "0.8"

43 changes: 5 additions & 38 deletions elementsd-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

#[cfg(test)]
mod pset;
#[cfg(test)]
mod taproot;

use elementsd::bitcoincore_rpc::RpcApi;
use elementsd::bitcoincore_rpc::jsonrpc::serde_json::{json, Value};
use elementsd::bitcoincore_rpc::RpcApi;
#[cfg(test)]
use elementsd::bitcoind::{self, BitcoinD};
use elementsd::ElementsD;
Expand Down Expand Up @@ -33,7 +32,10 @@ trait Call {

impl Call for ElementsD {
fn call(&self, cmd: &str, args: &[Value]) -> Value {
self.client().call::<Value>(cmd, args).unwrap()
match self.client().call::<Value>(cmd, args) {
Ok(v) => v,
Err(e) => panic!("error {} while calling {} with {:?}", e, cmd, args),
}
}

fn decode_psbt(&self, psbt: &str) -> Option<Value> {
Expand Down Expand Up @@ -132,45 +134,10 @@ impl Call for ElementsD {
.unwrap()
.to_string()
}

}

#[cfg(test)]
fn setup(validate_pegin: bool) -> (ElementsD, Option<BitcoinD>) {
// Create env var BITCOIND_EXE_PATH to point to the ../bitcoind/bin/bitcoind binary
let key = "BITCOIND_EXE";
if std::env::var(key).is_err() {
let mut root_path = std::env::current_dir().unwrap();
while std::fs::metadata(root_path.join("LICENSE")).is_err() {
if !root_path.pop() {
panic!("Could not find LICENSE file; do not know where repo root is.");
}
}

let bitcoind_path = root_path
.join("elementsd-tests")
.join("bin")
.join("bitcoind");
std::env::set_var(key, bitcoind_path);
}

// Create env var BITCOIND_EXE_PATH to point to the ../bitcoind/bin/bitcoind binary
let key = "ELEMENTSD_EXE";
if std::env::var(key).is_err() {
let mut root_path = std::env::current_dir().unwrap();
while std::fs::metadata(root_path.join("LICENSE")).is_err() {
if !root_path.pop() {
panic!("Could not find LICENSE file; do not know where repo root is.");
}
}

let bitcoind_path = root_path
.join("elementsd-tests")
.join("bin")
.join("elementsd");
std::env::set_var(key, bitcoind_path);
}

let mut bitcoind = None;
if validate_pegin {
let bitcoind_exe = bitcoind::exe_path().unwrap();
Expand Down
17 changes: 7 additions & 10 deletions src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::fmt;
use std::fmt::Write as _;
use std::str::FromStr;

use crate::bech32::{Bech32, Bech32m, ByteIterExt, Fe32, Fe32IterExt, Hrp};
use bech32::{Bech32, Bech32m, ByteIterExt, Fe32, Fe32IterExt, Hrp};
use crate::blech32::{Blech32, Blech32m};
use crate::hashes::Hash;
use bitcoin::base58;
Expand All @@ -44,7 +44,7 @@ pub enum AddressError {
/// Base58 encoding error
Base58(base58::Error),
/// Bech32 encoding error
Bech32(crate::bech32::primitives::decode::SegwitHrpstringError),
Bech32(bech32::primitives::decode::SegwitHrpstringError),
/// Blech32 encoding error
Blech32(crate::blech32::decode::SegwitHrpstringError),
/// Was unable to parse the address.
Expand All @@ -70,8 +70,8 @@ pub enum AddressError {
InvalidAddressVersion(u8),
}

impl From<crate::bech32::primitives::decode::SegwitHrpstringError> for AddressError {
fn from(e: crate::bech32::primitives::decode::SegwitHrpstringError) -> Self {
impl From<bech32::primitives::decode::SegwitHrpstringError> for AddressError {
fn from(e: bech32::primitives::decode::SegwitHrpstringError) -> Self {
AddressError::Bech32(e)
}
}
Expand Down Expand Up @@ -458,7 +458,7 @@ impl Address {
let hs = crate::blech32::decode::SegwitHrpstring::new(s)?;
(hs.witness_version(), hs.byte_iter().collect())
} else {
let hs = crate::bech32::primitives::decode::SegwitHrpstring::new(s)?;
let hs = bech32::primitives::decode::SegwitHrpstring::new(s)?;
(hs.witness_version(), hs.byte_iter().collect())
};

Expand Down Expand Up @@ -908,7 +908,7 @@ mod test {
"ert130xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqqu2tys".parse();
assert_eq!(
address.err().unwrap().to_string(),
"bech32 error: invalid segwit witness version: 3", // FIXME https://github.com/rust-bitcoin/rust-bech32/issues/162 should be 17
"bech32 error: invalid segwit witness version: 17 (bech32 character: '3')",
);

let address: Result<Address, _> = "el1pq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9jfn0gypaj".parse();
Expand All @@ -920,10 +920,7 @@ mod test {
// "invalid prefix" gives a weird error message because we do
// a dumb prefix check before even attempting bech32 decoding
let address: Result<Address, _> = "rrr1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfs2d9rp7meq4kg".parse();
assert_eq!(
address.err().unwrap().to_string(),
"base58 error: invalid base58 character 0x30",
);
assert_eq!(address.err().unwrap().to_string(), "base58 error: decode",);
}

#[test]
Expand Down
14 changes: 7 additions & 7 deletions src/blech32/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@
use core::{fmt, iter, slice, str};

use crate::error::write_err;
use crate::bech32::primitives::checksum::{self, Checksum};
use crate::bech32::primitives::gf32::Fe32;
use crate::bech32::primitives::hrp::{self, Hrp};
use crate::bech32::primitives::iter::{Fe32IterExt, FesToBytes};
use crate::bech32::primitives::segwit::{WitnessLengthError, VERSION_0};
use bech32::primitives::checksum::{self, Checksum};
use bech32::primitives::gf32::Fe32;
use bech32::primitives::hrp::{self, Hrp};
use bech32::primitives::iter::{Fe32IterExt, FesToBytes};
use bech32::primitives::segwit::{WitnessLengthError, VERSION_0};
use super::{Blech32, Blech32m};

/// Separator between the hrp and payload (as defined by BIP-173).
Expand Down Expand Up @@ -150,7 +150,7 @@ impl<'s> UncheckedHrpstring<'s> {
}

let mut checksum_eng = checksum::Engine::<Ck>::new();
checksum_eng.input_hrp(&self.hrp());
checksum_eng.input_hrp(self.hrp());

// Unwrap ok since we checked all characters in our constructor.
for fe in self.data.iter().map(|&b| Fe32::from_char(b.into()).unwrap()) {
Expand Down Expand Up @@ -881,7 +881,7 @@ mod tests {
"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio";

let hrp = Hrp::parse_unchecked(hrps);
let s = crate::bech32::encode::<Blech32>(hrp, &[]).expect("failed to encode empty buffer");
let s = bech32::encode::<Blech32>(hrp, &[]).expect("failed to encode empty buffer");

let unchecked = UncheckedHrpstring::new(&s).expect("failed to parse address");
assert_eq!(unchecked.hrp(), hrp);
Expand Down
9 changes: 6 additions & 3 deletions src/blech32/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub mod decode;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Blech32 {}

impl crate::bech32::Checksum for Blech32 {
impl bech32::Checksum for Blech32 {
type MidstateRepr = u64;
const CHECKSUM_LENGTH: usize = 12;
const GENERATOR_SH: [u64; 5] = [
Expand All @@ -37,13 +37,15 @@ impl crate::bech32::Checksum for Blech32 {
0x7093e5a608865b,
];
const TARGET_RESIDUE: u64 = 1;

const CODE_LENGTH: usize = 1024;
}

/// The blech32m checksum algorithm.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Blech32m {}

impl crate::bech32::Checksum for Blech32m {
impl bech32::Checksum for Blech32m {
type MidstateRepr = u64;
const CHECKSUM_LENGTH: usize = 12;
const GENERATOR_SH: [u64; 5] = [
Expand All @@ -54,5 +56,6 @@ impl crate::bech32::Checksum for Blech32m {
0x7093e5a608865b,
];
const TARGET_RESIDUE: u64 = 0x455972a3350f7a1;
}

const CODE_LENGTH: usize = 1024;
}
6 changes: 3 additions & 3 deletions src/blind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1375,7 +1375,7 @@ mod tests {
use crate::encode::deserialize;
use crate::hex::FromHex;
use crate::Script;
use bitcoin::{Network, PrivateKey, PublicKey};
use bitcoin::{PrivateKey, PublicKey};
use rand::thread_rng;
use secp256k1_zkp::SECP256K1;
use std::str::FromStr;
Expand Down Expand Up @@ -1466,7 +1466,7 @@ mod tests {
SECP256K1,
&PrivateKey {
compressed: true,
network: Network::Regtest,
network: bitcoin::NetworkKind::Test,
inner: sk,
},
);
Expand All @@ -1475,7 +1475,7 @@ mod tests {
SECP256K1,
&PrivateKey {
compressed: true,
network: Network::Regtest,
network: bitcoin::NetworkKind::Test,
inner: blinding_sk,
},
);
Expand Down
27 changes: 12 additions & 15 deletions src/hash_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,39 @@
//! to avoid mixing data of the same hash format (like SHA256d) but of different meaning
//! (transaction id, block hash etc).

use crate:: hashes::{hash_newtype, hash160, sha256, sha256d, Hash};
use bitcoin::secp256k1::ThirtyTwoByteHash;
use crate::hashes::{hash160, hash_newtype, sha256, sha256d, Hash};

macro_rules! impl_hashencode {
($hashtype:ident) => {
impl $crate::encode::Encodable for $hashtype {
fn consensus_encode<W: std::io::Write>(&self, w: W) -> Result<usize, crate::encode::Error> {
fn consensus_encode<W: std::io::Write>(
&self,
w: W,
) -> Result<usize, crate::encode::Error> {
self.0.consensus_encode(w)
}
}

impl $crate::encode::Decodable for $hashtype {
fn consensus_decode<R: std::io::Read>(r: R) -> Result<Self, $crate::encode::Error> {
Ok(Self::from_byte_array(<<$hashtype as $crate::hashes::Hash>::Bytes>::consensus_decode(r)?))
Ok(Self::from_byte_array(
<<$hashtype as $crate::hashes::Hash>::Bytes>::consensus_decode(r)?,
))
}
}
};
}

hash_newtype! {
/// An elements transaction ID
pub struct Txid(sha256d::Hash);
pub struct Txid(sha256d::Hash);
/// An elements witness transaction ID
pub struct Wtxid(sha256d::Hash);
pub struct Wtxid(sha256d::Hash);
/// An elements blockhash
pub struct BlockHash(sha256d::Hash);
pub struct BlockHash(sha256d::Hash);

/// "Hash of the transaction according to the signature algorithm"
pub struct Sighash(sha256d::Hash);
pub struct Sighash(sha256d::Hash);

/// A hash of a public key.
pub struct PubkeyHash(hash160::Hash);
Expand All @@ -59,15 +63,8 @@ hash_newtype! {
pub struct TxMerkleNode(sha256d::Hash);
}


impl_hashencode!(Txid);
impl_hashencode!(Wtxid);
impl_hashencode!(Sighash);
impl_hashencode!(BlockHash);
impl_hashencode!(TxMerkleNode);

impl ThirtyTwoByteHash for Sighash {
fn into_32(self) -> [u8; 32] {
self.0.to_byte_array()
}
}
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ mod transaction;
// consider making upstream public
mod endian;
// re-export bitcoin deps which we re-use
pub use bitcoin::bech32;
pub use bitcoin::hashes;
// export everything at the top level so it can be used as `elements::Transaction` etc.
pub use crate::address::{Address, AddressError, AddressParams};
Expand Down
2 changes: 1 addition & 1 deletion src/pset/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub enum Error {

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
match self {
Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey),
Error::InvalidProprietaryKey => write!(
f,
Expand Down
10 changes: 5 additions & 5 deletions src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,29 +261,29 @@ impl Script {

/// Generates P2WPKH-type of scriptPubkey
pub fn new_v0_wpkh(pubkey_hash: &WPubkeyHash) -> Script {
Script::new_witness_program(crate::bech32::Fe32::Q, &pubkey_hash.to_raw_hash().to_byte_array())
Script::new_witness_program(bech32::Fe32::Q, &pubkey_hash.to_raw_hash().to_byte_array())
}

/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
pub fn new_v0_wsh(script_hash: &WScriptHash) -> Script {
Script::new_witness_program(crate::bech32::Fe32::Q, &script_hash.to_raw_hash().to_byte_array())
Script::new_witness_program(bech32::Fe32::Q, &script_hash.to_raw_hash().to_byte_array())
}

/// Generates P2TR for script spending path using an internal public key and some optional
/// script tree merkle root.
pub fn new_v1_p2tr<C: Verification>(secp: &Secp256k1<C>, internal_key: UntweakedPublicKey, merkle_root: Option<TapNodeHash>) -> Script {
let (output_key, _) = internal_key.tap_tweak(secp, merkle_root);
Script::new_witness_program(crate::bech32::Fe32::P, &output_key.as_inner().serialize())
Script::new_witness_program(bech32::Fe32::P, &output_key.as_inner().serialize())
}

/// Generates P2TR for key spending path for a known [`TweakedPublicKey`].
pub fn new_v1_p2tr_tweaked(output_key: TweakedPublicKey) -> Script {
Script::new_witness_program(crate::bech32::Fe32::P, &output_key.as_inner().serialize())
Script::new_witness_program(bech32::Fe32::P, &output_key.as_inner().serialize())
}


/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
pub fn new_witness_program(ver: crate::bech32::Fe32, program: &[u8]) -> Script {
pub fn new_witness_program(ver: bech32::Fe32, program: &[u8]) -> Script {
let mut verop = ver.to_u8();
assert!(verop <= 16, "incorrect witness version provided: {}", verop);
if verop > 0 {
Expand Down

0 comments on commit 85604b0

Please sign in to comment.