diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1861b0b8..2f83e9c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,6 +40,7 @@ jobs: cross: true target_file: target/arm-unknown-linux-gnueabihf/release-arm/quill asset_name: quill-linux-arm32 + features: [static-ssl, hsm] - os: ubuntu-latest name: linux target_file: target/release/quill @@ -59,6 +60,7 @@ jobs: key: ${{ matrix.os }}-cargo-${{ env.rust }}-release-1 - name: Install dependencies + if: ${{ matrix.build_deps }} run: ${{ matrix.build_deps }} - name: Install toolchain diff --git a/Cargo.toml b/Cargo.toml index fd819d39..b2450871 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,12 +36,12 @@ crc32fast = "1.3.2" data-encoding = "2.3.3" flate2 = "1.0.22" hex = { version = "0.4.2", features = ["serde"] } -hidapi = { version = "1.4", default-features = false } +hidapi = { version = "1.4", default-features = false, optional = true } indicatif = "0.17" itertools = "0.10.5" k256 = { version = "0.11.4", features = ["pem"] } -ledger-apdu = "0.10" -ledger-transport-hid = "0.10" +ledger-apdu = { version = "0.10", optional = true } +ledger-transport-hid = { version = "0.10", optional = true } num-bigint = "0.4.3" once_cell = "1.17.1" openssl = "0.10.48" @@ -68,7 +68,8 @@ serial_test = "2.0.0" [features] static-ssl = ["openssl/vendored"] hsm = ["dep:ic-identity-hsm"] -default = ["static-ssl", "hsm"] +ledger = ["dep:hidapi", "dep:ledger-apdu", "dep:ledger-transport-hid"] +default = ["static-ssl", "hsm", "ledger"] [profile.release] opt-level = 2 diff --git a/Cross.toml b/Cross.toml index f42970aa..985438dd 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,2 +1,2 @@ [build] -pre-build = "./scripts/workflows/provision-linux-build.sh" +pre-build = "scripts/workflows/provision-linux-build.sh" diff --git a/scripts/workflows/provision-linux-build.sh b/scripts/workflows/provision-linux-build.sh index 87197b72..ac598859 100755 --- a/scripts/workflows/provision-linux-build.sh +++ b/scripts/workflows/provision-linux-build.sh @@ -3,10 +3,13 @@ set -euxo pipefail if [[ $# = 1 ]]; then # docker dpkg --add-architecture "$CROSS_DEB_ARCH" + if [[ $1 != "arm-"* && $1 != *"-musl" ]]; then + arch=":$CROSS_DEB_ARCH" + fi sudo() { "$@" } fi sudo apt-get update -y -sudo apt-get install libudev-dev:"${CROSS_DEB_ARCH:-amd64}" libssl-dev -y +sudo apt-get install "libudev-dev${arch+":$arch"}" libssl-dev -y diff --git a/src/commands/claim_neurons.rs b/src/commands/claim_neurons.rs index 4095e5d2..9828e73b 100644 --- a/src/commands/claim_neurons.rs +++ b/src/commands/claim_neurons.rs @@ -1,6 +1,7 @@ +#[cfg(feature = "ledger")] +use crate::lib::ledger::LedgerIdentity; use crate::lib::{ genesis_token_canister_id, - ledger::LedgerIdentity, signing::{sign_ingress_with_request_status_query, IngressWithRequestId}, AnyhowResult, AuthInfo, ROLE_NNS_GTC, }; @@ -27,16 +28,6 @@ pub fn exec(auth: &AuthInfo) -> AnyhowResult> { )?; let sig = Encode!(&hex::encode(bytes))?; - Ok(vec![sign_ingress_with_request_status_query( - auth, - genesis_token_canister_id(), - ROLE_NNS_GTC, - "claim_neurons", - sig, - )?]) - } else if let AuthInfo::Ledger = auth { - let (_, pk) = LedgerIdentity::new()?.public_key()?; - let sig = Encode!(&hex::encode(pk))?; Ok(vec![sign_ingress_with_request_status_query( auth, genesis_token_canister_id(), @@ -45,8 +36,25 @@ pub fn exec(auth: &AuthInfo) -> AnyhowResult> { sig, )?]) } else { + #[cfg(feature = "ledger")] + if let AuthInfo::Ledger = auth { + let (_, pk) = LedgerIdentity::new()?.public_key()?; + let sig = Encode!(&hex::encode(pk))?; + Ok(vec![sign_ingress_with_request_status_query( + auth, + genesis_token_canister_id(), + ROLE_NNS_GTC, + "claim_neurons", + sig, + )?]) + } else { + Err(anyhow!( + "claim-neurons command requires --pem-file or --ledger to be specified" + )) + } + #[cfg(not(feature = "ledger"))] Err(anyhow!( - "claim-neurons command requires --pem-file or --ledger to be specified" + "claim-neurons command requires --pem-file to be specified" )) } } diff --git a/src/commands/public.rs b/src/commands/public.rs index 8333249e..d5dd25c4 100644 --- a/src/commands/public.rs +++ b/src/commands/public.rs @@ -1,4 +1,6 @@ -use crate::lib::{get_account_id, get_identity, ledger::LedgerIdentity, AnyhowResult, AuthInfo}; +#[cfg(feature = "ledger")] +use crate::lib::ledger::LedgerIdentity; +use crate::lib::{get_account_id, get_identity, AnyhowResult, AuthInfo}; use anyhow::{anyhow, bail, Context}; use candid::Principal; use clap::Parser; @@ -16,6 +18,7 @@ pub struct PublicOpts { #[clap(long, conflicts_with = "principal-id")] genesis_dfn: bool, /// If authenticating with a Ledger device, display the public IDs on the device. + #[cfg_attr(not(feature = "ledger"), clap(hidden = true))] #[clap(long, requires = "ledgerhq")] display_on_ledger: bool, } @@ -32,7 +35,14 @@ pub fn exec(auth: &AuthInfo, opts: PublicOpts) -> AnyhowResult { println!("DFN address: {}", get_dfn(pem)?) } if opts.display_on_ledger { - LedgerIdentity::new()?.display_pk()?; + #[cfg(feature = "ledger")] + { + LedgerIdentity::new()?.display_pk()?; + } + #[cfg(not(feature = "ledger"))] + { + bail!("This build of quill does not support Ledger functionality."); + } } Ok(()) } diff --git a/src/lib/mod.rs b/src/lib/mod.rs index d8701c0b..91d3879c 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -40,6 +40,7 @@ use std::{ }; use std::{str::FromStr, time::SystemTime}; +#[cfg(feature = "ledger")] use self::ledger::LedgerIdentity; pub const IC_URL: &str = "https://ic0.app"; @@ -48,6 +49,7 @@ pub fn get_ic_url() -> String { env::var("IC_URL").unwrap_or_else(|_| IC_URL.to_string()) } +#[cfg(feature = "ledger")] pub mod ledger; pub mod signing; @@ -97,6 +99,7 @@ pub enum AuthInfo { PemFile(String), // --private-pem file specified #[cfg(feature = "hsm")] Pkcs11Hsm(HSMInfo), + #[cfg(feature = "ledger")] Ledger, } @@ -324,6 +327,7 @@ pub fn get_identity(auth: &AuthInfo) -> AnyhowResult> { .context("Unable to use your hardware key")?; Ok(Box::new(identity) as _) } + #[cfg(feature = "ledger")] AuthInfo::Ledger => Ok(Box::new(LedgerIdentity::new()?)), } } diff --git a/src/lib/signing.rs b/src/lib/signing.rs index a8f34a27..118e9b53 100644 --- a/src/lib/signing.rs +++ b/src/lib/signing.rs @@ -9,6 +9,7 @@ use serde_cbor::Value; use std::convert::TryFrom; use std::time::Duration; +#[cfg(feature = "ledger")] use super::ledger::LedgerIdentity; use super::{get_agent, get_default_role}; @@ -111,10 +112,11 @@ pub fn sign( method_name: &str, args: Vec, role: &str, - is_staking: bool, + #[allow(unused)] is_staking: bool, ) -> AnyhowResult { let ingress_expiry = Duration::from_secs(5 * 60); let agent = get_agent(auth)?; + #[cfg(feature = "ledger")] if is_staking && matches!(auth, AuthInfo::Ledger) { LedgerIdentity::new()?.next_stake(); } diff --git a/src/main.rs b/src/main.rs index 0f7fd8a2..5c081cef 100755 --- a/src/main.rs +++ b/src/main.rs @@ -70,6 +70,7 @@ struct GlobalOpts { seed_file: Option, /// Authenticate using a Ledger hardware wallet. + #[cfg_attr(not(feature = "ledger"), clap(hidden = true))] #[clap(long, global = true, groups = &["ledgerhq", "auth"])] ledger: bool, @@ -128,7 +129,14 @@ fn get_auth(opts: GlobalOpts) -> AnyhowResult { anyhow::bail!("This build of quill does not support HSM functionality.") } } else if opts.ledger { - Ok(AuthInfo::Ledger) + #[cfg(feature = "ledger")] + { + Ok(AuthInfo::Ledger) + } + #[cfg(not(feature = "ledger"))] + { + anyhow::bail!("This build of quill does not support Ledger functionality.") + } } else { pem_auth(opts) } diff --git a/tests/output-tests/main.rs b/tests/output-tests/main.rs index 8a18864c..62c74e9a 100644 --- a/tests/output-tests/main.rs +++ b/tests/output-tests/main.rs @@ -126,6 +126,7 @@ fn escape_p(p: &impl AsRef) -> String { macro_rules! ledger_compatible { ($($name:ident),* $(,)?) => { $( + #[cfg(feature = "ledger")] mod $name { #[test] #[serial_test::serial(ledger)] @@ -158,6 +159,7 @@ impl Default for AuthSettings { } } +#[cfg(feature = "ledger")] impl AuthSettings { fn ledger() -> Self { Self { @@ -187,6 +189,7 @@ impl Display for AccountIdPlaceholder { thread_local! { static AUTH_SETTINGS: RefCell = RefCell::default(); } +#[cfg(feature = "ledger")] fn with_ledger(f: impl FnOnce()) { struct ResetGuard; impl Drop for ResetGuard {