diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 84cbfb30..be8b186c 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -25,7 +25,7 @@ jobs: with: toolchain: ${{ matrix.rust }} - - name: Run cargo check Windows + - name: Run cargo check run: cargo check test: @@ -48,7 +48,7 @@ jobs: toolchain: stable - name: Run cargo test - run: cargo test + run: cargo test --release lints: name: Lints diff --git a/pallas-applying/src/lib.rs b/pallas-applying/src/lib.rs index 9d12f9d5..2e1ba463 100644 --- a/pallas-applying/src/lib.rs +++ b/pallas-applying/src/lib.rs @@ -31,13 +31,7 @@ pub fn validate_txs( ) -> ValidationResult { let mut delta_state: CertState = cert_state.clone(); for (txix, metx) in metxs.iter().enumerate() { - validate_tx( - &metx, - txix.try_into().unwrap(), - env, - utxos, - &mut delta_state, - )?; + validate_tx(metx, txix.try_into().unwrap(), env, utxos, &mut delta_state)?; } *cert_state = delta_state; Ok(()) @@ -67,7 +61,7 @@ pub fn validate_tx( utxos, cert_state, spp, - &acnt, + acnt, env.block_slot(), env.network_id(), &metx.era(), diff --git a/pallas-applying/src/shelley_ma.rs b/pallas-applying/src/shelley_ma.rs index 597c540f..098ef063 100644 --- a/pallas-applying/src/shelley_ma.rs +++ b/pallas-applying/src/shelley_ma.rs @@ -29,8 +29,10 @@ use pallas_traverse::{ time::Slot, wellknown::GenesisValues, ComputeHash, Era, MultiEraInput, MultiEraOutput, }; -use std::{cmp::max, collections::HashMap, ops::Deref}; // TODO: remove when fixed missing args +use std::{cmp::max, collections::HashMap, ops::Deref}; +// TODO: remove when fixed missing args +#[allow(clippy::too_many_arguments)] pub fn validate_shelley_ma_tx( mtx: &MintedTx, txix: TransactionIndex, @@ -63,7 +65,7 @@ pub fn validate_shelley_ma_tx( stk_dep_count, stk_refund_count, pool_count, - &acnt, + acnt, block_slot, &stab_win, prot_pps, @@ -229,8 +231,8 @@ fn get_produced( // Adding fees res = add_values(&res, &Value::Coin(tx_body.fee), &neg_val_err)?; // Pool reg deposits and staking key registrations - let total_deposits = prot_pps.pool_deposit * *pool_count + - prot_pps.key_deposit * *stk_dep_count; + let total_deposits = + prot_pps.pool_deposit * *pool_count + prot_pps.key_deposit * *stk_dep_count; res = add_values(&res, &Value::Coin(total_deposits), &neg_val_err)?; Ok(res) } @@ -407,6 +409,7 @@ fn compute_script_hash(script: &NativeScript) -> PolicyId { } // Checks all certificates in order, and counts the relevant ones for computing deposits. +#[allow(clippy::too_many_arguments)] fn check_certificates( cert_opt: &Option>, tx_ix: TransactionIndex, @@ -452,7 +455,7 @@ fn check_certificates( relays, pool_metadata, } => { - if !cert_state.pstate.pool_params.contains_key(&operator) { + if !cert_state.pstate.pool_params.contains_key(operator) { *pool_count += 1; } let pool_param = PoolParam { @@ -551,7 +554,7 @@ where V: Clone, { if map.contains_key(key) { - return Err(error); + Err(error) } else { map.insert(key.clone(), value.clone()); Ok(()) @@ -568,14 +571,12 @@ fn check_pool_reg_or_update( Err(ShelleyMA(PoolCostBelowMin)) } else if ps.pool_params.contains_key(pool_hash) { // Updating - ps.fut_pool_params - .insert(pool_hash.clone(), (*pool_param).clone()); - ps.retiring.remove(&pool_hash); + ps.fut_pool_params.insert(*pool_hash, (*pool_param).clone()); + ps.retiring.remove(pool_hash); Ok(()) } else { // Registering - ps.pool_params - .insert(pool_hash.clone(), (*pool_param).clone()); + ps.pool_params.insert(*pool_hash, (*pool_param).clone()); Ok(()) } } @@ -587,11 +588,11 @@ fn check_pool_retirement( emax: &u32, ps: &mut PState, ) -> ValidationResult { - if !ps.pool_params.contains_key(&pool_hash) { + if !ps.pool_params.contains_key(pool_hash) { return Err(ShelleyMA(PoolNotRegistered)); } if (*cepoch < *repoch) & (*repoch <= *cepoch + *emax as u64) { - ps.retiring.insert(pool_hash.clone(), *repoch); + ps.retiring.insert(*pool_hash, *repoch); Ok(()) } else { Err(ShelleyMA(PoolNotRegistered)) @@ -633,7 +634,7 @@ fn check_genesis_key_delegation( } else { let gen_slot: Slot = *slot + *stab_win; ds.fut_gen_delegs - .insert((gen_slot, gkh.clone()), (dkh.clone(), vrf.clone())); + .insert((gen_slot, gkh.clone()), (dkh.clone(), *vrf)); Ok(()) } } @@ -646,7 +647,7 @@ fn check_mir( acnt: &AccountState, ) -> ValidationResult { let genesis = &GenesisValues::mainnet(); - if !(*slot < first_slot(genesis, &(to_epoch(genesis, slot) + 1)) - *stab_win) { + if *slot >= first_slot(genesis, &(to_epoch(genesis, slot) + 1)) - *stab_win { Err(ShelleyMA(MIRCertificateTooLateinEpoch)) } else { let (ir_reserves, ir_treasury) = ds.inst_rewards.clone(); @@ -655,16 +656,13 @@ fn check_mir( Treasury => (acnt.treasury, ir_treasury.clone()), }; let mut combined: HashMap = HashMap::new(); - match &mir.target { - StakeCredentials(kvp) => { - let mut kvv: Vec<(StakeCredential, u64)> = // TODO: Err if the value is negative - kvp.iter().map(|kv| (kv.clone().0, kv.clone().1 as u64)).collect(); - kvv.extend(ir_pot); - for (key, value) in kvv { - combined.insert(key, value); - } + if let StakeCredentials(kvp) = &mir.target { + let mut kvv: Vec<(StakeCredential, u64)> = // TODO: Err if the value is negative + kvp.iter().map(|kv| (kv.clone().0, kv.clone().1 as u64)).collect(); + kvv.extend(ir_pot); + for (key, value) in kvv { + combined.insert(key, value); } - _ => (), } if combined.iter().map(|kv| kv.1).sum::() > pot { return Err(ShelleyMA(InsufficientForInstantaneousRewards)); diff --git a/pallas-applying/tests/shelley_ma.rs b/pallas-applying/tests/shelley_ma.rs index 75ddcb88..7f43017a 100644 --- a/pallas-applying/tests/shelley_ma.rs +++ b/pallas-applying/tests/shelley_ma.rs @@ -2,6 +2,7 @@ pub mod common; use common::*; use pallas_addresses::{Address, Network, ShelleyAddress}; +use pallas_applying::utils::PoolParam; use pallas_applying::{ utils::{ AccountState, Environment, MultiEraProtocolParameters, ShelleyMAError, ShelleyProtParams, @@ -18,18 +19,16 @@ use pallas_codec::{ }; use pallas_crypto::hash::Hash; use pallas_primitives::alonzo::{ - MintedTx, MintedWitnessSet, Nonce, NonceVariant, RationalNumber, StakeCredential, - TransactionBody, TransactionOutput, VKeyWitness, Value, PoolMetadata, Relay, - PoolKeyhash, Certificate, + Certificate, MintedTx, MintedWitnessSet, Nonce, NonceVariant, PoolKeyhash, PoolMetadata, + RationalNumber, Relay, StakeCredential, TransactionBody, TransactionOutput, VKeyWitness, Value, }; use pallas_traverse::{Era, MultiEraTx}; use std::str::FromStr; -use pallas_applying::utils::PoolParam; #[cfg(test)] mod shelley_ma_tests { use super::*; - + #[test] // Transaction hash: // 50eba65e73c8c5f7b09f4ea28cf15dce169f3d1c322ca3deff03725f51518bb2 @@ -468,7 +467,11 @@ mod shelley_ma_tests { Err(err) => panic!("Unexpected error ({:?})", err), }; - if !cert_state.pstate.pool_params.contains_key(&mary2_pool_operator()) { + if !cert_state + .pstate + .pool_params + .contains_key(&mary2_pool_operator()) + { panic!("Pool not registered or keyhash mismatch"); } } @@ -484,15 +487,13 @@ mod shelley_ma_tests { let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Mary); let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx( &mtx.transaction_body, - &[( - String::from(MARY3_UTXO), - Value::Coin(627_760_000), - None, - )], + &[(String::from(MARY3_UTXO), Value::Coin(627_760_000), None)], ); let mut cert_state: CertState = CertState::default(); - cert_state.pstate.pool_params + cert_state + .pstate + .pool_params .insert(mary2_pool_operator(), mary2_pool_param()); match validate_txs(&[metx], &mary3_env(), &utxos, &mut cert_state) { Ok(()) => (), @@ -503,24 +504,41 @@ mod shelley_ma_tests { fn mary2_pool_operator() -> PoolKeyhash { Hash::from_str("59EBE72AE96462018FBE04633100F90B3066688D85F00F3BD254707F").unwrap() } - + // Params for the pool registered in `successful_mainnet_mary_tx_with_pool_reg` fn mary2_pool_param() -> PoolParam { PoolParam { - vrf_keyhash: Hash::from_str("1EFB798F239B9B02DEB4636A3AB1962AF43512595FCB82276E11971E684E49B7").unwrap(), + vrf_keyhash: Hash::from_str( + "1EFB798F239B9B02DEB4636A3AB1962AF43512595FCB82276E11971E684E49B7", + ) + .unwrap(), pledge: 1000000000, cost: 340000000, - margin: RationalNumber { numerator: 3, denominator: 100 }, - reward_account: hex::decode("E1FB2B631DB76384F64DD94B47F97FC8C2A206764C17A1DE7DA2F70E83").unwrap().into(), - pool_owners: Vec::from([Hash::from_str("FB2B631DB76384F64DD94B47F97FC8C2A206764C17A1DE7DA2F70E83").unwrap()]), - relays: [ - Relay::SingleHostAddr(Nullable::Some(3001), - Nullable::Some(hex::decode("C22614BB").unwrap().into()), - Nullable::Null,) - ].to_vec(), + margin: RationalNumber { + numerator: 3, + denominator: 100, + }, + reward_account: hex::decode( + "E1FB2B631DB76384F64DD94B47F97FC8C2A206764C17A1DE7DA2F70E83", + ) + .unwrap() + .into(), + pool_owners: Vec::from([Hash::from_str( + "FB2B631DB76384F64DD94B47F97FC8C2A206764C17A1DE7DA2F70E83", + ) + .unwrap()]), + relays: [Relay::SingleHostAddr( + Nullable::Some(3001), + Nullable::Some(hex::decode("C22614BB").unwrap().into()), + Nullable::Null, + )] + .to_vec(), pool_metadata: Nullable::Some(PoolMetadata { url: "https://cardapool.com/a.json".to_string(), - hash: Hash::from_str("01F708549816C9A075FF96E9682C11A5F5C7F4E147862A663BDEECE0716AB76E").unwrap(), + hash: Hash::from_str( + "01F708549816C9A075FF96E9682C11A5F5C7F4E147862A663BDEECE0716AB76E", + ) + .unwrap(), }), } } @@ -1785,11 +1803,7 @@ mod shelley_ma_tests { let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Mary); let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx( &mtx.transaction_body, - &[( - String::from(MARY3_UTXO), - Value::Coin(627_760_000), - None, - )], + &[(String::from(MARY3_UTXO), Value::Coin(627_760_000), None)], ); let mut cert_state: CertState = CertState::default(); @@ -1827,15 +1841,13 @@ mod shelley_ma_tests { let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx( &mtx.transaction_body, - &[( - String::from(MARY3_UTXO), - Value::Coin(627_760_000), - None, - )], + &[(String::from(MARY3_UTXO), Value::Coin(627_760_000), None)], ); let mut cert_state: CertState = CertState::default(); - cert_state.pstate.pool_params + cert_state + .pstate + .pool_params .insert(mary2_pool_operator(), mary2_pool_param()); match validate_txs(&[metx], &mary3_env(), &utxos, &mut cert_state) { Ok(()) => panic!("Staking key is not registered"),