Skip to content

Commit

Permalink
Feature-gate the executable auto-download
Browse files Browse the repository at this point in the history
This way all the build-deps are not used when auto-download is not required
granting a MSRV of 1.41.1
  • Loading branch information
RCasatta committed Jan 5, 2023
1 parent 5e4a925 commit 67bb3da
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 170 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
strategy:
fail-fast: false
matrix:
toolchain: [ "1.57.0", "stable", "nightly" ]
toolchain: [ "1.41.1", "stable", "nightly" ]

steps:
- uses: actions/checkout@v2
Expand Down
38 changes: 19 additions & 19 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,26 @@ which = "4.2.5"
anyhow = "1.0.66"

[dev-dependencies]
env_logger = "0.9"
env_logger = "0.9.0"

[build-dependencies]
bitcoin_hashes = "0.11"
filetime = "0.2"
flate2 = "1.0"
tar = "0.4"
ureq = "2.5.0"
zip = "0.6"
time = "=0.3.10" # otherwise rust 1.57 fails to select time "^0.3.7"
bitcoin_hashes = { version = "0.11", optional = true }
filetime = { version = "0.2", optional = true }
flate2 = { version = "1.0", optional = true }
tar = { version = "0.4", optional = true }
ureq = { version = "2.5.0", optional = true }
zip = { version = "0.6", optional = true }

[features]
"23_0" = []
"22_0" = []
"0_21_1" = []
"0_21_0" = []
"0_20_1" = []
"0_20_0" = []
"0_19_1" = []
"0_19_0_1" = []
"0_18_1" = []
"0_18_0" = []
"0_17_1" = []
"download" = [ "bitcoin_hashes", "filetime", "flate2", "tar", "ureq", "zip"]
"23_0" = ["download"]
"22_0" = ["download"]
"0_21_1" = ["download"]
"0_21_0" = ["download"]
"0_20_1" = ["download"]
"0_20_0" = ["download"]
"0_19_1" = ["download"]
"0_19_0_1" = ["download"]
"0_18_1" = ["download"]
"0_18_0" = ["download"]
"0_17_1" = ["download"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ let bitcoind = bitcoind::BitcoinD::new(bitcoind::downloaded_exe_path().unwrap())

## MSRV

The MSRV is 1.41 for versions up to 0.27.\*, and 1.57 from 0.28.0.
The MSRV is 1.41.1 for version 0.29.* if no feature is used, otherwise is 1.57

## Issues with traditional approach

Expand Down
270 changes: 141 additions & 129 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,148 +1,160 @@
use bitcoin_hashes::{sha256, Hash};
use flate2::read::GzDecoder;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read};
use std::path::Path;
use std::str::FromStr;
use tar::Archive;

include!("src/versions.rs");

#[cfg(all(
target_os = "macos",
any(target_arch = "x86_64", target_arch = "aarch64"),
))]
fn download_filename() -> String {
if cfg!(any(
feature = "22_0",
feature = "0_21_1",
feature = "0_21_0",
feature = "0_20_1",
feature = "0_20_0",
feature = "0_19_1",
feature = "0_19_0_1",
feature = "0_18_1",
feature = "0_18_0",
feature = "0_17_1",
)) {
format!("bitcoin-{}-osx64.tar.gz", &VERSION)
} else {
format!("bitcoin-{}-x86_64-apple-darwin.tar.gz", &VERSION)
}
}
#[cfg(not(feature = "download"))]
mod download {}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-x86_64-linux-gnu.tar.gz", &VERSION)
}
#[cfg(not(feature = "download"))]
fn main() {}

#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
fn download_filename() -> String {
format!("bitcoin-{}-aarch64-linux-gnu.tar.gz", &VERSION)
#[cfg(feature = "download")]
fn main() {
download::start();
}

#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-win64.zip", &VERSION)
}
#[cfg(feature = "download")]
mod download {

use bitcoin_hashes::{sha256, Hash};
use flate2::read::GzDecoder;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read};
use std::path::Path;
use std::str::FromStr;
use tar::Archive;

include!("src/versions.rs");

fn get_expected_sha256(filename: &str) -> sha256::Hash {
let sha256sums_filename = format!("sha256/bitcoin-core-{}-SHA256SUMS", &VERSION);
#[cfg(any(
feature = "0_21_1",
feature = "0_21_0",
feature = "0_20_1",
feature = "0_20_0",
feature = "0_19_1",
feature = "0_19_0_1",
feature = "0_18_1",
feature = "0_18_0",
feature = "0_17_1",
#[cfg(all(
target_os = "macos",
any(target_arch = "x86_64", target_arch = "aarch64"),
))]
let sha256sums_filename = format!("{}.asc", sha256sums_filename);
let file = File::open(&sha256sums_filename).unwrap();
for line in BufReader::new(file).lines().flatten() {
let tokens: Vec<_> = line.split(" ").collect();
if tokens.len() == 2 && filename == tokens[1] {
return sha256::Hash::from_str(tokens[0]).unwrap();
fn download_filename() -> String {
if cfg!(any(
feature = "22_0",
feature = "0_21_1",
feature = "0_21_0",
feature = "0_20_1",
feature = "0_20_0",
feature = "0_19_1",
feature = "0_19_0_1",
feature = "0_18_1",
feature = "0_18_0",
feature = "0_17_1",
)) {
format!("bitcoin-{}-osx64.tar.gz", &VERSION)
} else {
format!("bitcoin-{}-x86_64-apple-darwin.tar.gz", &VERSION)
}
}
panic!(
"Couldn't find hash for `{}` in `{}`:\n{}",
filename,
sha256sums_filename,
std::fs::read_to_string(&sha256sums_filename).unwrap()
);
}

fn main() {
if !HAS_FEATURE {
return;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-x86_64-linux-gnu.tar.gz", &VERSION)
}

#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
fn download_filename() -> String {
format!("bitcoin-{}-aarch64-linux-gnu.tar.gz", &VERSION)
}
let download_filename = download_filename();
let expected_hash = get_expected_sha256(&download_filename);
let out_dir = std::env::var_os("OUT_DIR").unwrap();
let mut bitcoin_exe_home = Path::new(&out_dir).join("bitcoin");
if !bitcoin_exe_home.exists() {
std::fs::create_dir(&bitcoin_exe_home).unwrap();

#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-win64.zip", &VERSION)
}
let existing_filename = bitcoin_exe_home
.join(format!("bitcoin-{}", VERSION))
.join("bin")
.join("bitcoind");

if !existing_filename.exists() {
println!(
"filename:{} version:{} hash:{}",
download_filename, VERSION, expected_hash
);

let url = format!(
"https://bitcoincore.org/bin/bitcoin-core-{}/{}",
VERSION, download_filename
fn get_expected_sha256(filename: &str) -> sha256::Hash {
let sha256sums_filename = format!("sha256/bitcoin-core-{}-SHA256SUMS", &VERSION);
#[cfg(any(
feature = "0_21_1",
feature = "0_21_0",
feature = "0_20_1",
feature = "0_20_0",
feature = "0_19_1",
feature = "0_19_0_1",
feature = "0_18_1",
feature = "0_18_0",
feature = "0_17_1",
))]
let sha256sums_filename = format!("{}.asc", sha256sums_filename);
let file = File::open(&sha256sums_filename).unwrap();
for line in BufReader::new(file).lines().flatten() {
let tokens: Vec<_> = line.split(" ").collect();
if tokens.len() == 2 && filename == tokens[1] {
return sha256::Hash::from_str(tokens[0]).unwrap();
}
}
panic!(
"Couldn't find hash for `{}` in `{}`:\n{}",
filename,
sha256sums_filename,
std::fs::read_to_string(&sha256sums_filename).unwrap()
);
println!("url:{}", url);
let mut downloaded_bytes = Vec::new();
let resp = ureq::get(&url).call().unwrap();
assert_eq!(resp.status(), 200, "url {} didn't return 200", url);

let _size = resp
.into_reader()
.read_to_end(&mut downloaded_bytes)
.unwrap();
let downloaded_hash = sha256::Hash::hash(&downloaded_bytes);
assert_eq!(expected_hash, downloaded_hash);

if download_filename.ends_with(".tar.gz") {
let d = GzDecoder::new(&downloaded_bytes[..]);

let mut archive = Archive::new(d);
for mut entry in archive.entries().unwrap().flatten() {
if let Ok(file) = entry.path() {
if file.ends_with("bitcoind") {
entry.unpack_in(&bitcoin_exe_home).unwrap();
}

pub(crate) fn start() {
let download_filename = download_filename();
let expected_hash = get_expected_sha256(&download_filename);
let out_dir = std::env::var_os("OUT_DIR").unwrap();
let mut bitcoin_exe_home = Path::new(&out_dir).join("bitcoin");
if !bitcoin_exe_home.exists() {
std::fs::create_dir(&bitcoin_exe_home).unwrap();
}
let existing_filename = bitcoin_exe_home
.join(format!("bitcoin-{}", VERSION))
.join("bin")
.join("bitcoind");

if !existing_filename.exists() {
println!(
"filename:{} version:{} hash:{}",
download_filename, VERSION, expected_hash
);

let url = format!(
"https://bitcoincore.org/bin/bitcoin-core-{}/{}",
VERSION, download_filename
);
println!("url:{}", url);
let mut downloaded_bytes = Vec::new();
let resp = ureq::get(&url).call().unwrap();
assert_eq!(resp.status(), 200, "url {} didn't return 200", url);

let _size = resp
.into_reader()
.read_to_end(&mut downloaded_bytes)
.unwrap();
let downloaded_hash = sha256::Hash::hash(&downloaded_bytes);
assert_eq!(expected_hash, downloaded_hash);

if download_filename.ends_with(".tar.gz") {
let d = GzDecoder::new(&downloaded_bytes[..]);

let mut archive = Archive::new(d);
for mut entry in archive.entries().unwrap().flatten() {
if let Ok(file) = entry.path() {
if file.ends_with("bitcoind") {
entry.unpack_in(&bitcoin_exe_home).unwrap();
}
}
}
}
} else if download_filename.ends_with(".zip") {
let cursor = Cursor::new(downloaded_bytes);
let mut archive = zip::ZipArchive::new(cursor).unwrap();
for i in 0..zip::ZipArchive::len(&archive) {
let mut file = archive.by_index(i).unwrap();
let outpath = match file.enclosed_name() {
Some(path) => path.to_owned(),
None => continue,
};

if outpath.file_name().map(|s| s.to_str()) == Some(Some("bitcoind.exe")) {
for d in outpath.iter() {
bitcoin_exe_home.push(d);
} else if download_filename.ends_with(".zip") {
let cursor = Cursor::new(downloaded_bytes);
let mut archive = zip::ZipArchive::new(cursor).unwrap();
for i in 0..zip::ZipArchive::len(&archive) {
let mut file = archive.by_index(i).unwrap();
let outpath = match file.enclosed_name() {
Some(path) => path.to_owned(),
None => continue,
};

if outpath.file_name().map(|s| s.to_str()) == Some(Some("bitcoind.exe")) {
for d in outpath.iter() {
bitcoin_exe_home.push(d);
}
std::fs::create_dir_all(&bitcoin_exe_home.parent().unwrap()).unwrap();
println!("{:?}", bitcoin_exe_home);
let mut outfile = std::fs::File::create(&bitcoin_exe_home).unwrap();
io::copy(&mut file, &mut outfile).unwrap();
break;
}
std::fs::create_dir_all(&bitcoin_exe_home.parent().unwrap()).unwrap();
println!("{:?}", bitcoin_exe_home);
let mut outfile = std::fs::File::create(&bitcoin_exe_home).unwrap();
io::copy(&mut file, &mut outfile).unwrap();
break;
}
}
}
Expand Down
Loading

0 comments on commit 67bb3da

Please sign in to comment.