audit-3 (code cleanup): zero clippy warnings, zero build warnings
prep for deployment. cargo clippy --workspace --all-targets now passes clean. cargo audit unchanged (same 2 unmaintained-warning macro-support transitives; no cves). cleanup applied: - ProtocolParams construction in tools.rs uses struct-update syntax (clippy::field_reassign_with_default). - main.rs collapsed two else-if branches with identical bodies (clippy::if_same_then_else). - mint/plutus/stake sort_by(|a,b| b.cmp(&a)) → sort_by_key(Reverse(_)) (clippy::manual_sort_by). 4 sites. - metadata/mint/tx odd-length hex check uses .is_multiple_of(2) (clippy::manual_is_multiple_of). 3 sites. - stake.rs witness_overhead conditional removed — both branches produced TWO_WITNESS_OVERHEAD_BYTES (left over from when registration was thought to add a third witness; it doesn't). WITNESS_OVERHEAD_BYTES const removed (only the two-witness one is used). - Public spend/mint/stake build_signed_*_with_assets fns get #[allow(clippy::too_many_arguments)] — they ARE the API surface. - ex_units_default_is_generous test gets explicit allow for the tautological-on-const assertion (kept the intent comment). 97 unit tests still pass. release build clean.
This commit is contained in:
parent
7d59ceffd2
commit
f23ff65dad
7 changed files with 30 additions and 25 deletions
|
|
@ -171,7 +171,7 @@ pub fn build_cip25_aux_data(
|
|||
}
|
||||
|
||||
fn decode_hex(s: &str) -> Result<Vec<u8>, WalletError> {
|
||||
if s.len() % 2 != 0 {
|
||||
if !s.len().is_multiple_of(2) {
|
||||
return Err(WalletError::Derivation("hex string odd length".into()));
|
||||
}
|
||||
let mut out = Vec::with_capacity(s.len() / 2);
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ fn parse_tx_hash(hex_str: &str) -> Result<Hash<32>, WalletError> {
|
|||
}
|
||||
|
||||
fn parse_asset_name(hex_str: &str) -> Result<Vec<u8>, WalletError> {
|
||||
if hex_str.len() % 2 != 0 {
|
||||
if !hex_str.len().is_multiple_of(2) {
|
||||
return Err(WalletError::Derivation(
|
||||
"asset_name hex must have even length".into(),
|
||||
));
|
||||
|
|
@ -259,7 +259,7 @@ fn prepare_mint(
|
|||
.ok_or_else(|| WalletError::Derivation("amount overflow".into()))?;
|
||||
|
||||
let mut sorted: Vec<InputUtxo> = available_utxos.to_vec();
|
||||
sorted.sort_by(|a, b| b.lovelace.cmp(&a.lovelace));
|
||||
sorted.sort_by_key(|u| std::cmp::Reverse(u.lovelace));
|
||||
let mut acc: u64 = 0;
|
||||
let mut selected: Vec<InputUtxo> = Vec::new();
|
||||
for u in sorted {
|
||||
|
|
@ -703,7 +703,7 @@ pub fn build_signed_cip68_nft_mint(
|
|||
.ok_or_else(|| WalletError::Derivation("amount overflow".into()))?;
|
||||
|
||||
let mut sorted: Vec<InputUtxo> = available_utxos.to_vec();
|
||||
sorted.sort_by(|a, b| b.lovelace.cmp(&a.lovelace));
|
||||
sorted.sort_by_key(|u| std::cmp::Reverse(u.lovelace));
|
||||
let mut acc: u64 = 0;
|
||||
let mut selected: Vec<InputUtxo> = Vec::new();
|
||||
for u in sorted {
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ pub fn build_signed_plutus_spend(
|
|||
.filter(|u| u.assets.is_empty())
|
||||
.cloned()
|
||||
.collect();
|
||||
ada_only.sort_by(|a, b| b.lovelace.cmp(&a.lovelace));
|
||||
ada_only.sort_by_key(|u| std::cmp::Reverse(u.lovelace));
|
||||
|
||||
// Pick collateral — largest ADA-only UTXO ≥ 5 ADA.
|
||||
let collateral = ada_only
|
||||
|
|
@ -359,7 +359,11 @@ mod tests {
|
|||
const UNIT_REDEEMER_CBOR: [u8; 3] = [0xd8, 0x79, 0x80];
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::assertions_on_constants)]
|
||||
fn ex_units_default_is_generous() {
|
||||
// Tautological today (DEFAULT_EX_UNITS is a const), but the
|
||||
// intent is to guard against a future shrink that would make
|
||||
// trivial validators fail to validate. Keep the check.
|
||||
assert!(DEFAULT_EX_UNITS.mem >= 1_000_000);
|
||||
assert!(DEFAULT_EX_UNITS.steps >= 100_000_000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ use crate::{Network, PaymentKey, ProtocolParams, StakeKey, WalletError};
|
|||
/// Shelley). Refunded on deregistration.
|
||||
pub const STAKE_KEY_DEPOSIT_LOVELACE: u64 = 2_000_000;
|
||||
|
||||
const WITNESS_OVERHEAD_BYTES: u64 = 128;
|
||||
/// Two witnesses (payment + stake) instead of just one — used for fee
|
||||
/// estimation when both keys sign.
|
||||
/// estimation. Both `register_first` paths sign with both keys, so the
|
||||
/// witness overhead is constant.
|
||||
const TWO_WITNESS_OVERHEAD_BYTES: u64 = 256;
|
||||
|
||||
/// Decode a `pool1...` bech32 pool ID into a 28-byte Hash.
|
||||
|
|
@ -84,6 +84,7 @@ fn network_id_for(network: Network) -> u8 {
|
|||
///
|
||||
/// The tx is signed by both the payment key (body witness) and the
|
||||
/// stake key (cert witness). Returned CBOR is ready for submission.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn build_signed_stake_delegation(
|
||||
payment_key: &PaymentKey,
|
||||
stake_key: &StakeKey,
|
||||
|
|
@ -129,7 +130,7 @@ pub fn build_signed_stake_delegation(
|
|||
.ok_or_else(|| WalletError::Derivation("amount overflow".into()))?;
|
||||
|
||||
let mut sorted: Vec<InputUtxo> = available_utxos.to_vec();
|
||||
sorted.sort_by(|a, b| b.lovelace.cmp(&a.lovelace));
|
||||
sorted.sort_by_key(|u| std::cmp::Reverse(u.lovelace));
|
||||
let mut acc: u64 = 0;
|
||||
let mut selected: Vec<InputUtxo> = Vec::new();
|
||||
for u in sorted {
|
||||
|
|
@ -210,15 +211,9 @@ pub fn build_signed_stake_delegation(
|
|||
.map_err(|e| WalletError::Derivation(format!("conway build (pass1): {e}")))?
|
||||
.tx_bytes
|
||||
.0;
|
||||
// Two witnesses for delegation: payment + stake. Fee estimate
|
||||
// accounts for both.
|
||||
let witness_overhead = if register_first {
|
||||
TWO_WITNESS_OVERHEAD_BYTES
|
||||
} else {
|
||||
TWO_WITNESS_OVERHEAD_BYTES
|
||||
};
|
||||
let _ = WITNESS_OVERHEAD_BYTES; // silence unused if both branches use the two-witness constant
|
||||
let est_signed = (unsigned.len() as u64) + witness_overhead;
|
||||
// Both delegation cases sign with two witnesses (payment + stake);
|
||||
// registration doesn't add a third.
|
||||
let est_signed = (unsigned.len() as u64) + TWO_WITNESS_OVERHEAD_BYTES;
|
||||
let real_fee = params.min_fee_for_size(est_signed);
|
||||
|
||||
let token_change = !input_assets.is_empty();
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ fn parse_policy_id(hex_str: &str) -> Result<pallas_crypto::hash::Hash<28>, Walle
|
|||
}
|
||||
|
||||
fn parse_asset_name(hex_str: &str) -> Result<Vec<u8>, WalletError> {
|
||||
if hex_str.len() % 2 != 0 {
|
||||
if !hex_str.len().is_multiple_of(2) {
|
||||
return Err(WalletError::Derivation(
|
||||
"asset_name hex must have even length".into(),
|
||||
));
|
||||
|
|
@ -364,6 +364,7 @@ fn output_with_assets(
|
|||
Ok(out)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_staging_with_fee(
|
||||
inputs: &[InputUtxo],
|
||||
to_addr: &PallasAddress,
|
||||
|
|
@ -632,7 +633,7 @@ fn hex_encode(bytes: &[u8]) -> String {
|
|||
/// Hex-decode a string into a Vec — used by the cold-sign flow to
|
||||
/// turn the externally-signed tx hex back into bytes for submission.
|
||||
pub fn hex_decode(s: &str) -> Result<Vec<u8>, WalletError> {
|
||||
if s.len() % 2 != 0 {
|
||||
if !s.len().is_multiple_of(2) {
|
||||
return Err(WalletError::Derivation("hex string has odd length".into()));
|
||||
}
|
||||
let mut out = Vec::with_capacity(s.len() / 2);
|
||||
|
|
@ -671,6 +672,7 @@ pub fn build_signed_payment(
|
|||
|
||||
/// Build + sign a Conway-era payment that may include native assets.
|
||||
/// Returns the signed CBOR bytes ready for `ChainBackend::submit_tx`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn build_signed_payment_with_assets(
|
||||
payment_key: &PaymentKey,
|
||||
network: Network,
|
||||
|
|
@ -722,6 +724,7 @@ pub fn build_unsigned_payment(
|
|||
/// signing. Returns the unsigned CBOR + a `PaymentSummary` for human
|
||||
/// review. Caller signs externally and submits via
|
||||
/// `ChainBackend::submit_tx`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn build_unsigned_payment_with_assets(
|
||||
network: Network,
|
||||
available_utxos: &[InputUtxo],
|
||||
|
|
@ -887,7 +890,7 @@ mod tests {
|
|||
#[test]
|
||||
fn parse_asset_name_validates_length() {
|
||||
assert!(parse_asset_name(&"ab".repeat(33)).is_err()); // > 32 bytes
|
||||
assert!(parse_asset_name(&"deadbeef").is_ok()); // 4 bytes
|
||||
assert!(parse_asset_name("deadbeef").is_ok()); // 4 bytes
|
||||
assert!(parse_asset_name("").is_ok()); // 0 bytes — valid (ADA-symbol-like)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,9 +82,10 @@ async fn run() -> Result<()> {
|
|||
let (payment_key, stake_key, address) = {
|
||||
let root = if bootstrap_new {
|
||||
bootstrap::generate_and_save_root_key(&cfg.data_dir)?
|
||||
} else if mnemonic_path.exists() {
|
||||
bootstrap::load_or_create_root_key(&cfg.data_dir)?
|
||||
} else if bootstrap_only {
|
||||
} else if mnemonic_path.exists() || bootstrap_only {
|
||||
// Both branches load (or create on the bootstrap path).
|
||||
// `load_or_create_root_key` itself decides which based on
|
||||
// whether `mnemonic.age` exists.
|
||||
bootstrap::load_or_create_root_key(&cfg.data_dir)?
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
|
|
|
|||
|
|
@ -826,8 +826,10 @@ impl WalletService {
|
|||
// verify script_data_hash. Hardcoded preprod value from
|
||||
// koios epoch_params; future improvement is pulling fresh
|
||||
// from the chain on each call. (PLUTUS-4 audit fix.)
|
||||
let mut params = ProtocolParams::default();
|
||||
params.plutus_v3_cost_model = Some(PLUTUS_V3_COST_MODEL_PREPROD.to_vec());
|
||||
let params = ProtocolParams {
|
||||
plutus_v3_cost_model: Some(PLUTUS_V3_COST_MODEL_PREPROD.to_vec()),
|
||||
..ProtocolParams::default()
|
||||
};
|
||||
|
||||
let cbor = build_signed_plutus_spend(
|
||||
&self.inner.payment_key,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue