mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-11-17 15:26:14 +00:00
Merge #253
253: Monero rpc installer for windows r=rishflab a=rishflab I could not find an async zip archive extractor. The download is still async. One potential follow up could be to spawn the extraction of the zip in the windows path. Closes #228 Co-authored-by: rishflab <rishflab@hotmail.com>
This commit is contained in:
commit
31475ab07d
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -44,12 +44,14 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: [ x86_64-unknown-linux-gnu, x86_64-apple-darwin ]
|
target: [ x86_64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-pc-windows-msvc ]
|
||||||
include:
|
include:
|
||||||
- target: x86_64-unknown-linux-gnu
|
- target: x86_64-unknown-linux-gnu
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- target: x86_64-apple-darwin
|
- target: x86_64-apple-darwin
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
|
- target: x86_64-pc-windows-msvc
|
||||||
|
os: windows-latest
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
2
.github/workflows/release-cli.yml
vendored
2
.github/workflows/release-cli.yml
vendored
@ -14,6 +14,8 @@ jobs:
|
|||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- target: x86_64-apple-darwin
|
- target: x86_64-apple-darwin
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
|
- target: x86_64-pc-windows-msvc
|
||||||
|
os: windows-latest
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout tagged commit
|
- name: Checkout tagged commit
|
||||||
|
66
Cargo.lock
generated
66
Cargo.lock
generated
@ -1,5 +1,11 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "adler32"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aead"
|
name = "aead"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -121,7 +127,7 @@ version = "0.3.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b72c1f1154e234325b50864a349b9c8e56939e266a4c307c0f159812df2f9537"
|
checksum = "b72c1f1154e234325b50864a349b9c8e56939e266a4c307c0f159812df2f9537"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bzip2",
|
"bzip2 0.4.2",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"memchr",
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@ -498,6 +504,16 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
|
||||||
|
dependencies = [
|
||||||
|
"bzip2-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bzip2"
|
name = "bzip2"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@ -1068,6 +1084,18 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10",
|
||||||
|
"crc32fast",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -1979,6 +2007,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.7.7"
|
version = "0.7.7"
|
||||||
@ -3580,7 +3617,7 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"testcontainers 0.12.0",
|
"testcontainers 0.12.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time 0.2.24",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tar",
|
"tokio-tar",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
@ -3593,6 +3630,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
"void",
|
"void",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3722,6 +3760,16 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.2.24"
|
version = "0.2.24"
|
||||||
@ -4452,3 +4500,17 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a8977234acab718eb2820494b2f96cbb16004c19dddf88b7445b27381450997"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"bzip2 0.3.3",
|
||||||
|
"crc32fast",
|
||||||
|
"flate2",
|
||||||
|
"thiserror",
|
||||||
|
"time 0.1.43",
|
||||||
|
]
|
||||||
|
@ -2,6 +2,7 @@ status = [
|
|||||||
"static_analysis",
|
"static_analysis",
|
||||||
"build (x86_64-unknown-linux-gnu)",
|
"build (x86_64-unknown-linux-gnu)",
|
||||||
"build (x86_64-apple-darwin)",
|
"build (x86_64-apple-darwin)",
|
||||||
|
"build (x86_64-pc-windows-msvc)",
|
||||||
"test (x86_64-unknown-linux-gnu)",
|
"test (x86_64-unknown-linux-gnu)",
|
||||||
"test (x86_64-apple-darwin)",
|
"test (x86_64-apple-darwin)",
|
||||||
"docker_tests (happy_path)",
|
"docker_tests (happy_path)",
|
||||||
|
@ -51,7 +51,6 @@ strum = { version = "0.20", features = ["derive"] }
|
|||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
time = "0.2"
|
time = "0.2"
|
||||||
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "macros", "sync", "process", "fs"] }
|
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "macros", "sync", "process", "fs"] }
|
||||||
tokio-tar = { path = "../tokio-tar" }
|
|
||||||
tokio-tungstenite = { version = "0.13", features = [ "tls" ] }
|
tokio-tungstenite = { version = "0.13", features = [ "tls" ] }
|
||||||
tokio-util = { version = "0.6.3", features = ["io"] }
|
tokio-util = { version = "0.6.3", features = ["io"] }
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
@ -63,6 +62,12 @@ url = { version = "2.1", features = ["serde"] }
|
|||||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
void = "1"
|
void = "1"
|
||||||
|
|
||||||
|
[target.'cfg(not(windows))'.dependencies]
|
||||||
|
tokio-tar = { path = "../tokio-tar" }
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
zip = "0.5"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bitcoin-harness = { git = "https://github.com/coblox/bitcoin-harness-rs" }
|
bitcoin-harness = { git = "https://github.com/coblox/bitcoin-harness-rs" }
|
||||||
get-port = "3"
|
get-port = "3"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use ::monero::Network;
|
use ::monero::Network;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use async_compression::tokio::bufread::BzDecoder;
|
|
||||||
use big_bytes::BigByte;
|
use big_bytes::BigByte;
|
||||||
use futures::{StreamExt, TryStreamExt};
|
use futures::{StreamExt, TryStreamExt};
|
||||||
use reqwest::{header::CONTENT_LENGTH, Url};
|
use reqwest::{header::CONTENT_LENGTH, Url};
|
||||||
@ -14,23 +13,33 @@ use tokio::{
|
|||||||
io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
|
io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
|
||||||
process::{Child, Command},
|
process::{Child, Command},
|
||||||
};
|
};
|
||||||
use tokio_tar::Archive;
|
|
||||||
use tokio_util::{
|
use tokio_util::{
|
||||||
codec::{BytesCodec, FramedRead},
|
codec::{BytesCodec, FramedRead},
|
||||||
io::StreamReader,
|
io::StreamReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
|
||||||
|
compile_error!("unsupported operating system");
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
const DOWNLOAD_URL: &str = "http://downloads.getmonero.org/cli/monero-mac-x64-v0.17.1.9.tar.bz2";
|
const DOWNLOAD_URL: &str = "http://downloads.getmonero.org/cli/monero-mac-x64-v0.17.1.9.tar.bz2";
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.17.1.9.tar.bz2";
|
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.17.1.9.tar.bz2";
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
|
#[cfg(target_os = "windows")]
|
||||||
compile_error!("unsupported operating system");
|
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.17.1.9.zip";
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||||
const PACKED_FILE: &str = "monero-wallet-rpc";
|
const PACKED_FILE: &str = "monero-wallet-rpc";
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
const PACKED_FILE: &str = "monero-wallet-rpc.exe";
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, thiserror::Error)]
|
||||||
|
#[error("monero wallet rpc executable not found in downloaded archive")]
|
||||||
|
pub struct ExecutableNotFoundInArchive;
|
||||||
|
|
||||||
pub struct WalletRpcProcess {
|
pub struct WalletRpcProcess {
|
||||||
_child: Child,
|
_child: Child,
|
||||||
port: u16,
|
port: u16,
|
||||||
@ -59,8 +68,8 @@ impl WalletRpc {
|
|||||||
working_dir: working_dir.to_path_buf(),
|
working_dir: working_dir.to_path_buf(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if monero_wallet_rpc.tar_path().exists() {
|
if monero_wallet_rpc.archive_path().exists() {
|
||||||
remove_file(monero_wallet_rpc.tar_path()).await?;
|
remove_file(monero_wallet_rpc.archive_path()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !monero_wallet_rpc.exec_path().exists() {
|
if !monero_wallet_rpc.exec_path().exists() {
|
||||||
@ -69,7 +78,7 @@ impl WalletRpc {
|
|||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.create_new(true)
|
.create_new(true)
|
||||||
.open(monero_wallet_rpc.tar_path())
|
.open(monero_wallet_rpc.archive_path())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let response = reqwest::get(DOWNLOAD_URL).await?;
|
let response = reqwest::get(DOWNLOAD_URL).await?;
|
||||||
@ -88,43 +97,28 @@ impl WalletRpc {
|
|||||||
.bytes_stream()
|
.bytes_stream()
|
||||||
.map_err(|err| std::io::Error::new(ErrorKind::Other, err));
|
.map_err(|err| std::io::Error::new(ErrorKind::Other, err));
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
let mut stream = FramedRead::new(
|
let mut stream = FramedRead::new(
|
||||||
BzDecoder::new(StreamReader::new(byte_stream)),
|
async_compression::tokio::bufread::BzDecoder::new(StreamReader::new(byte_stream)),
|
||||||
BytesCodec::new(),
|
BytesCodec::new(),
|
||||||
)
|
)
|
||||||
.map_ok(|bytes| bytes.freeze());
|
.map_ok(|bytes| bytes.freeze());
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let mut stream = FramedRead::new(StreamReader::new(byte_stream), BytesCodec::new())
|
||||||
|
.map_ok(|bytes| bytes.freeze());
|
||||||
|
|
||||||
while let Some(chunk) = stream.next().await {
|
while let Some(chunk) = stream.next().await {
|
||||||
file.write(&chunk?).await?;
|
file.write(&chunk?).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.flush().await?;
|
file.flush().await?;
|
||||||
|
|
||||||
let mut options = OpenOptions::new();
|
Self::extract_archive(&monero_wallet_rpc).await?;
|
||||||
let file = options
|
|
||||||
.read(true)
|
|
||||||
.open(monero_wallet_rpc.tar_path())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mut ar = Archive::new(file);
|
|
||||||
let mut entries = ar.entries()?;
|
|
||||||
|
|
||||||
while let Some(file) = entries.next().await {
|
|
||||||
let mut f = file?;
|
|
||||||
if f.path()?
|
|
||||||
.to_str()
|
|
||||||
.context("Could not find convert path to str in tar ball")?
|
|
||||||
.contains(PACKED_FILE)
|
|
||||||
{
|
|
||||||
f.unpack(monero_wallet_rpc.exec_path()).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_file(monero_wallet_rpc.tar_path()).await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(monero_wallet_rpc)
|
Ok(monero_wallet_rpc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&self, network: Network, daemon_host: &str) -> Result<WalletRpcProcess> {
|
pub async fn run(&self, network: Network, daemon_host: &str) -> Result<WalletRpcProcess> {
|
||||||
let port = tokio::net::TcpListener::bind("127.0.0.1:0")
|
let port = tokio::net::TcpListener::bind("127.0.0.1:0")
|
||||||
.await?
|
.await?
|
||||||
@ -169,11 +163,78 @@ impl WalletRpc {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tar_path(&self) -> PathBuf {
|
fn archive_path(&self) -> PathBuf {
|
||||||
self.working_dir.join("monero-cli-wallet.tar")
|
self.working_dir.join("monero-cli-wallet.archive")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_path(&self) -> PathBuf {
|
fn exec_path(&self) -> PathBuf {
|
||||||
self.working_dir.join(PACKED_FILE)
|
self.working_dir.join(PACKED_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
async fn extract_archive(monero_wallet_rpc: &Self) -> Result<()> {
|
||||||
|
use anyhow::bail;
|
||||||
|
use tokio_tar::Archive;
|
||||||
|
|
||||||
|
let mut options = OpenOptions::new();
|
||||||
|
let file = options
|
||||||
|
.read(true)
|
||||||
|
.open(monero_wallet_rpc.archive_path())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut ar = Archive::new(file);
|
||||||
|
let mut entries = ar.entries()?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match entries.next().await {
|
||||||
|
Some(file) => {
|
||||||
|
let mut f = file?;
|
||||||
|
if f.path()?
|
||||||
|
.to_str()
|
||||||
|
.context("Could not find convert path to str in tar ball")?
|
||||||
|
.contains(PACKED_FILE)
|
||||||
|
{
|
||||||
|
f.unpack(monero_wallet_rpc.exec_path()).await?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => bail!(ExecutableNotFoundInArchive),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_file(monero_wallet_rpc.archive_path()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
async fn extract_archive(monero_wallet_rpc: &Self) -> Result<()> {
|
||||||
|
use std::fs::File;
|
||||||
|
use tokio::task::JoinHandle;
|
||||||
|
use zip::ZipArchive;
|
||||||
|
|
||||||
|
let archive_path = monero_wallet_rpc.archive_path();
|
||||||
|
let exec_path = monero_wallet_rpc.exec_path();
|
||||||
|
|
||||||
|
let extract: JoinHandle<Result<()>> = tokio::task::spawn_blocking(|| {
|
||||||
|
let file = File::open(archive_path)?;
|
||||||
|
let mut zip = ZipArchive::new(file)?;
|
||||||
|
|
||||||
|
let name = zip
|
||||||
|
.file_names()
|
||||||
|
.find(|name| name.contains(PACKED_FILE))
|
||||||
|
.context(ExecutableNotFoundInArchive)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let mut rpc = zip.by_name(&name)?;
|
||||||
|
let mut file = File::create(exec_path)?;
|
||||||
|
std::io::copy(&mut rpc, &mut file)?;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
extract.await??;
|
||||||
|
|
||||||
|
remove_file(monero_wallet_rpc.archive_path()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user