From 983322d2730997bf552a73ff25294bb7d8e01d7e Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Sun, 19 Dec 2021 15:54:11 +0000 Subject: [PATCH] Feature/refactor mixnet contract test helpers (#986) * Refactored test helpers * Renaming mixnode "bond" coins to "pledge" * Renaming gateway "bond" coins to "pledge" * ibid * Commenting out new tests, they will go in next PR --- contracts/Cargo.lock | 12 + contracts/mixnet/Cargo.toml | 1 + contracts/mixnet/src/contract.rs | 4 +- .../mixnet/src/delegations/transactions.rs | 115 +++++-- contracts/mixnet/src/gateways/queries.rs | 25 +- contracts/mixnet/src/gateways/storage.rs | 8 +- contracts/mixnet/src/gateways/transactions.rs | 74 ++--- .../mixnet/src/mixnodes/bonding_queries.rs | 26 +- contracts/mixnet/src/mixnodes/storage.rs | 8 +- contracts/mixnet/src/mixnodes/transactions.rs | 113 ++++--- contracts/mixnet/src/rewards/queries.rs | 22 +- contracts/mixnet/src/rewards/transactions.rs | 65 ++-- contracts/mixnet/src/support/tests.rs | 296 ------------------ .../mixnet/src/support/tests/fixtures.rs | 93 ++++++ .../mixnet/src/support/tests/messages.rs | 44 +++ contracts/mixnet/src/support/tests/mod.rs | 130 ++++++++ contracts/mixnet/src/support/tests/queries.rs | 49 +++ contracts/mixnet/src/support/tests/signing.rs | 14 + 18 files changed, 624 insertions(+), 475 deletions(-) delete mode 100644 contracts/mixnet/src/support/tests.rs create mode 100644 contracts/mixnet/src/support/tests/fixtures.rs create mode 100644 contracts/mixnet/src/support/tests/messages.rs create mode 100644 contracts/mixnet/src/support/tests/mod.rs create mode 100644 contracts/mixnet/src/support/tests/queries.rs create mode 100644 contracts/mixnet/src/support/tests/signing.rs diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index a2ac4d14de..5009880cbd 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -317,6 +317,7 @@ dependencies = [ "blake3", "bs58", "cipher", + "config", "digest 0.9.0", "ed25519-dalek", "generic-array 0.14.4", @@ -326,6 +327,7 @@ dependencies = [ "nymsphinx-types", "pemstore", "rand", + "subtle-encoding", "x25519-dalek", ] @@ -852,6 +854,7 @@ dependencies = [ "cosmwasm-storage", "crypto", "cw-storage-plus", + "ed25519-dalek", "fixed", "mixnet-contract", "rand", @@ -1328,6 +1331,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "syn" version = "1.0.81" diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 52710764cc..c6e06d6aa1 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -29,6 +29,7 @@ cosmwasm-storage = "1.0.0-beta2" cw-storage-plus = "0.10.3" bs58 = "0.4.0" +ed25519-dalek = "1.0" schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.23" } diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 606eeaa28b..245888d88a 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -289,7 +289,7 @@ pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result>(); @@ -122,7 +123,7 @@ pub(crate) mod tests { let info = mock_info( &sender_identities[0].0.clone(), - &test_helpers::good_gateway_bond(), + &tests::fixtures::good_gateway_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[0].clone()).unwrap(); @@ -135,7 +136,7 @@ pub(crate) mod tests { // save another let info = mock_info( &sender_identities[1].0.clone(), - &test_helpers::good_gateway_bond(), + &tests::fixtures::good_gateway_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[1].clone()).unwrap(); @@ -145,7 +146,7 @@ pub(crate) mod tests { let info = mock_info( &sender_identities[2].0.clone(), - &test_helpers::good_gateway_bond(), + &tests::fixtures::good_gateway_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[2].clone()).unwrap(); @@ -167,7 +168,7 @@ pub(crate) mod tests { // save another one let info = mock_info( &sender_identities[3].0.clone(), - &test_helpers::good_gateway_bond(), + &tests::fixtures::good_gateway_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[3].clone()).unwrap(); @@ -191,13 +192,17 @@ pub(crate) mod tests { assert!(res.gateway.is_none()); // mixnode was added to "bob", "fred" still does not own one - test_helpers::add_gateway("bob", test_helpers::good_gateway_bond(), deps.as_mut()); + test_helpers::add_gateway("bob", tests::fixtures::good_gateway_pledge(), deps.as_mut()); let res = query_owns_gateway(deps.as_ref(), "fred".to_string()).unwrap(); assert!(res.gateway.is_none()); // "fred" now owns a gateway! - test_helpers::add_gateway("fred", test_helpers::good_gateway_bond(), deps.as_mut()); + test_helpers::add_gateway( + "fred", + tests::fixtures::good_gateway_pledge(), + deps.as_mut(), + ); let res = query_owns_gateway(deps.as_ref(), "fred".to_string()).unwrap(); assert!(res.gateway.is_some()); diff --git a/contracts/mixnet/src/gateways/storage.rs b/contracts/mixnet/src/gateways/storage.rs index f7ee1d3980..33b5ef9ab0 100644 --- a/contracts/mixnet/src/gateways/storage.rs +++ b/contracts/mixnet/src/gateways/storage.rs @@ -35,7 +35,7 @@ pub(crate) fn gateways<'a>() -> IndexedMap<'a, IdentityKeyRef<'a>, GatewayBond, #[cfg(test)] mod tests { use super::super::storage; - use crate::support::tests::test_helpers; + use crate::support::tests; use config::defaults::DENOM; use cosmwasm_std::testing::MockStorage; use cosmwasm_std::StdResult; @@ -57,8 +57,8 @@ mod tests { #[test] fn gateway_single_read_retrieval() { let mut storage = MockStorage::new(); - let bond1 = test_helpers::gateway_bond_fixture("owner1"); - let bond2 = test_helpers::gateway_bond_fixture("owner2"); + let bond1 = tests::fixtures::gateway_bond_fixture("owner1"); + let bond2 = tests::fixtures::gateway_bond_fixture("owner2"); storage::gateways() .save(&mut storage, "bond1", &bond1) .unwrap(); @@ -91,7 +91,7 @@ mod tests { block_height: 12_345, gateway: Gateway { identity_key: node_identity.clone(), - ..test_helpers::gateway_fixture() + ..tests::fixtures::gateway_fixture() }, proxy: None, }; diff --git a/contracts/mixnet/src/gateways/transactions.rs b/contracts/mixnet/src/gateways/transactions.rs index 0bd6439387..a33a23a3dd 100644 --- a/contracts/mixnet/src/gateways/transactions.rs +++ b/contracts/mixnet/src/gateways/transactions.rs @@ -201,6 +201,7 @@ pub mod tests { use crate::contract::{execute, query, INITIAL_GATEWAY_PLEDGE}; use crate::error::ContractError; use crate::gateways::transactions::validate_gateway_pledge; + use crate::support::tests; use crate::support::tests::test_helpers; use config::defaults::DENOM; use cosmwasm_std::attr; @@ -217,7 +218,7 @@ pub mod tests { // if we fail validation (by say not sending enough funds let insufficient_bond = Into::::into(INITIAL_GATEWAY_PLEDGE) - 1; let info = mock_info("anyone", &coins(insufficient_bond, DENOM)); - let (msg, _) = test_helpers::valid_bond_gateway_msg("anyone"); + let (msg, _) = tests::messages::valid_bond_gateway_msg("anyone"); // we are informed that we didn't send enough funds let result = execute(deps.as_mut(), mock_env(), info, msg); @@ -243,8 +244,8 @@ pub mod tests { assert_eq!(0, page.nodes.len()); // if we send enough funds - let info = mock_info("anyone", &test_helpers::good_gateway_bond()); - let (msg, identity) = test_helpers::valid_bond_gateway_msg("anyone"); + let info = mock_info("anyone", &tests::fixtures::good_gateway_pledge()); + let (msg, identity) = tests::messages::valid_bond_gateway_msg("anyone"); // we get back a message telling us everything was OK let execute_response = execute(deps.as_mut(), mock_env(), info, msg); @@ -265,18 +266,18 @@ pub mod tests { assert_eq!( &Gateway { identity_key: identity, - ..test_helpers::gateway_fixture() + ..tests::fixtures::gateway_fixture() }, page.nodes[0].gateway() ); // if there was already a gateway bonded by particular user - let info = mock_info("foomper", &test_helpers::good_gateway_bond()); - let (msg, _) = test_helpers::valid_bond_gateway_msg("foomper"); + let info = mock_info("foomper", &tests::fixtures::good_gateway_pledge()); + let (msg, _) = tests::messages::valid_bond_gateway_msg("foomper"); execute(deps.as_mut(), mock_env(), info, msg).unwrap(); - let info = mock_info("foomper", &test_helpers::good_gateway_bond()); - let (msg, _) = test_helpers::valid_bond_gateway_msg("foomper"); + let info = mock_info("foomper", &tests::fixtures::good_gateway_pledge()); + let (msg, _) = tests::messages::valid_bond_gateway_msg("foomper"); // it fails let execute_response = execute(deps.as_mut(), mock_env(), info, msg); @@ -285,12 +286,12 @@ pub mod tests { // bonding fails if the user already owns a mixnode test_helpers::add_mixnode( "mixnode-owner", - test_helpers::good_mixnode_bond(), + tests::fixtures::good_mixnode_pledge(), deps.as_mut(), ); - let info = mock_info("mixnode-owner", &test_helpers::good_gateway_bond()); - let (msg, _) = test_helpers::valid_bond_gateway_msg("mixnode-owner"); + let info = mock_info("mixnode-owner", &tests::fixtures::good_gateway_pledge()); + let (msg, _) = tests::messages::valid_bond_gateway_msg("mixnode-owner"); let execute_response = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(execute_response, Err(ContractError::AlreadyOwnsMixnode)); @@ -300,8 +301,8 @@ pub mod tests { let msg = ExecuteMsg::UnbondMixnode {}; execute(deps.as_mut(), mock_env(), info, msg).unwrap(); - let info = mock_info("mixnode-owner", &test_helpers::good_gateway_bond()); - let (msg, _) = test_helpers::valid_bond_gateway_msg("mixnode-owner"); + let info = mock_info("mixnode-owner", &tests::fixtures::good_gateway_pledge()); + let (msg, _) = tests::messages::valid_bond_gateway_msg("mixnode-owner"); let execute_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(execute_response.is_ok()); @@ -314,7 +315,7 @@ pub mod tests { fn adding_gateway_without_existing_owner() { let mut deps = test_helpers::init_contract(); - let info = mock_info("gateway-owner", &test_helpers::good_gateway_bond()); + let info = mock_info("gateway-owner", &tests::fixtures::good_gateway_pledge()); // before the execution the node had no associated owner assert!(storage::gateways() @@ -324,7 +325,7 @@ pub mod tests { .unwrap() .is_none()); - let (msg, identity) = test_helpers::valid_bond_gateway_msg("gateway-owner"); + let (msg, identity) = tests::messages::valid_bond_gateway_msg("gateway-owner"); // it's all fine, owner is saved let execute_response = execute(deps.as_mut(), mock_env(), info, msg); @@ -349,19 +350,19 @@ pub mod tests { let identity = test_helpers::add_gateway( "gateway-owner", - test_helpers::good_gateway_bond(), + tests::fixtures::good_gateway_pledge(), deps.as_mut(), ); // request fails giving the existing owner address in the message let info = mock_info( "gateway-owner-pretender", - &test_helpers::good_gateway_bond(), + &tests::fixtures::good_gateway_pledge(), ); let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: identity, - ..test_helpers::gateway_fixture() + ..tests::fixtures::gateway_fixture() }, owner_signature: "foomp".to_string(), }; @@ -381,12 +382,12 @@ pub mod tests { test_helpers::add_gateway( "gateway-owner", - test_helpers::good_gateway_bond(), + tests::fixtures::good_gateway_pledge(), deps.as_mut(), ); - let info = mock_info("gateway-owner", &test_helpers::good_gateway_bond()); - let (msg, _) = test_helpers::valid_bond_gateway_msg("gateway-owner"); + let info = mock_info("gateway-owner", &tests::fixtures::good_gateway_pledge()); + let (msg, _) = tests::messages::valid_bond_gateway_msg("gateway-owner"); let res = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(Err(ContractError::AlreadyOwnsGateway), res); @@ -410,7 +411,7 @@ pub mod tests { ); // let's add a node owned by bob - test_helpers::add_gateway("bob", test_helpers::good_gateway_bond(), deps.as_mut()); + test_helpers::add_gateway("bob", tests::fixtures::good_gateway_pledge(), deps.as_mut()); // attempt to unbond fred's node, which doesn't exist let info = mock_info("fred", &[]); @@ -424,18 +425,21 @@ pub mod tests { ); // bob's node is still there - let nodes = test_helpers::get_gateways(&mut deps); + let nodes = tests::queries::get_gateways(&mut deps); assert_eq!(1, nodes.len()); let first_node = &nodes[0]; assert_eq!(&Addr::unchecked("bob"), first_node.owner()); // add a node owned by fred - let fred_identity = - test_helpers::add_gateway("fred", test_helpers::good_gateway_bond(), deps.as_mut()); + let fred_identity = test_helpers::add_gateway( + "fred", + tests::fixtures::good_gateway_pledge(), + deps.as_mut(), + ); // let's make sure we now have 2 nodes: - assert_eq!(2, test_helpers::get_gateways(&mut deps).len()); + assert_eq!(2, tests::queries::get_gateways(&mut deps).len()); // unbond fred's node let info = mock_info("fred", &[]); @@ -458,7 +462,7 @@ pub mod tests { // we should see a funds transfer from the contract back to fred let expected_message = BankMsg::Send { to_address: String::from(info.sender), - amount: test_helpers::good_gateway_bond(), + amount: tests::fixtures::good_gateway_pledge(), }; // run the executor and check that we got back the correct results @@ -469,7 +473,7 @@ pub mod tests { assert_eq!(remove_fred, expected); // only 1 node now exists, owned by bob: - let gateway_bonds = test_helpers::get_gateways(&mut deps); + let gateway_bonds = tests::queries::get_gateways(&mut deps); assert_eq!(1, gateway_bonds.len()); assert_eq!(&Addr::unchecked("bob"), gateway_bonds[0].owner()); } @@ -478,8 +482,8 @@ pub mod tests { fn removing_gateway_clears_ownership() { let mut deps = test_helpers::init_contract(); - let info = mock_info("gateway-owner", &test_helpers::good_gateway_bond()); - let (bond_msg, identity) = test_helpers::valid_bond_gateway_msg("gateway-owner"); + let info = mock_info("gateway-owner", &tests::fixtures::good_gateway_pledge()); + let (bond_msg, identity) = tests::messages::valid_bond_gateway_msg("gateway-owner"); execute(deps.as_mut(), mock_env(), info, bond_msg.clone()).unwrap(); assert_eq!( @@ -507,7 +511,7 @@ pub mod tests { .is_none()); // and since it's removed, it can be reclaimed - let info = mock_info("gateway-owner", &test_helpers::good_gateway_bond()); + let info = mock_info("gateway-owner", &tests::fixtures::good_gateway_pledge()); assert!(execute(deps.as_mut(), mock_env(), info, bond_msg).is_ok()); assert_eq!( @@ -530,7 +534,7 @@ pub mod tests { assert_eq!(result, Err(ContractError::NoBondFound)); // you must send at least 100 coins... - let mut bond = test_helpers::good_gateway_bond(); + let mut bond = tests::fixtures::good_gateway_pledge(); bond[0].amount = INITIAL_GATEWAY_PLEDGE.checked_sub(Uint128::new(1)).unwrap(); let result = validate_gateway_pledge(bond.clone(), INITIAL_GATEWAY_PLEDGE); assert_eq!( @@ -542,18 +546,18 @@ pub mod tests { ); // more than that is still fine - let mut bond = test_helpers::good_gateway_bond(); + let mut bond = tests::fixtures::good_gateway_pledge(); bond[0].amount = INITIAL_GATEWAY_PLEDGE + Uint128::new(1); let result = validate_gateway_pledge(bond.clone(), INITIAL_GATEWAY_PLEDGE); assert!(result.is_ok()); // it must be sent in the defined denom! - let mut bond = test_helpers::good_gateway_bond(); + let mut bond = tests::fixtures::good_gateway_pledge(); bond[0].denom = "baddenom".to_string(); let result = validate_gateway_pledge(bond.clone(), INITIAL_GATEWAY_PLEDGE); assert_eq!(result, Err(ContractError::WrongDenom {})); - let mut bond = test_helpers::good_gateway_bond(); + let mut bond = tests::fixtures::good_gateway_pledge(); bond[0].denom = "foomp".to_string(); let result = validate_gateway_pledge(bond.clone(), INITIAL_GATEWAY_PLEDGE); assert_eq!(result, Err(ContractError::WrongDenom {})); diff --git a/contracts/mixnet/src/mixnodes/bonding_queries.rs b/contracts/mixnet/src/mixnodes/bonding_queries.rs index 2343f05010..4e485f1b77 100644 --- a/contracts/mixnet/src/mixnodes/bonding_queries.rs +++ b/contracts/mixnet/src/mixnodes/bonding_queries.rs @@ -64,9 +64,9 @@ pub fn query_owns_mixnode(deps: Deps, address: String) -> StdResult>(); @@ -138,7 +138,7 @@ pub(crate) mod tests { let info = mock_info( &sender_identities[0].0.clone(), - &test_helpers::good_mixnode_bond(), + &tests::fixtures::good_mixnode_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[0].clone()).unwrap(); @@ -151,7 +151,7 @@ pub(crate) mod tests { // save another let info = mock_info( &sender_identities[1].0.clone(), - &test_helpers::good_mixnode_bond(), + &tests::fixtures::good_mixnode_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[1].clone()).unwrap(); @@ -161,7 +161,7 @@ pub(crate) mod tests { let info = mock_info( &sender_identities[2].0.clone(), - &test_helpers::good_mixnode_bond(), + &tests::fixtures::good_mixnode_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[2].clone()).unwrap(); @@ -183,7 +183,7 @@ pub(crate) mod tests { // save another one let info = mock_info( &sender_identities[3].0.clone(), - &test_helpers::good_mixnode_bond(), + &tests::fixtures::good_mixnode_pledge(), ); execute(deps.as_mut(), mock_env(), info, messages[3].clone()).unwrap(); @@ -207,13 +207,17 @@ pub(crate) mod tests { assert!(res.mixnode.is_none()); // mixnode was added to "bob", "fred" still does not own one - test_helpers::add_mixnode("bob", test_helpers::good_mixnode_bond(), deps.as_mut()); + test_helpers::add_mixnode("bob", tests::fixtures::good_mixnode_pledge(), deps.as_mut()); let res = query_owns_mixnode(deps.as_ref(), "fred".to_string()).unwrap(); assert!(res.mixnode.is_none()); // "fred" now owns a mixnode! - test_helpers::add_mixnode("fred", test_helpers::good_mixnode_bond(), deps.as_mut()); + test_helpers::add_mixnode( + "fred", + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); let res = query_owns_mixnode(deps.as_ref(), "fred".to_string()).unwrap(); assert!(res.mixnode.is_some()); diff --git a/contracts/mixnet/src/mixnodes/storage.rs b/contracts/mixnet/src/mixnodes/storage.rs index 00add66360..cbbcf749b4 100644 --- a/contracts/mixnet/src/mixnodes/storage.rs +++ b/contracts/mixnet/src/mixnodes/storage.rs @@ -137,7 +137,7 @@ pub(crate) fn read_full_mixnode_bond( mod tests { use super::super::storage; use super::*; - use crate::support::tests::test_helpers; + use crate::support::tests; use config::defaults::DENOM; use cosmwasm_std::testing::MockStorage; use cosmwasm_std::{coin, Addr, Uint128}; @@ -147,8 +147,8 @@ mod tests { #[test] fn mixnode_single_read_retrieval() { let mut storage = MockStorage::new(); - let bond1 = test_helpers::stored_mixnode_bond_fixture("owner1"); - let bond2 = test_helpers::stored_mixnode_bond_fixture("owner2"); + let bond1 = tests::fixtures::stored_mixnode_bond_fixture("owner1"); + let bond2 = tests::fixtures::stored_mixnode_bond_fixture("owner2"); mixnodes().save(&mut storage, "bond1", &bond1).unwrap(); mixnodes().save(&mut storage, "bond2", &bond2).unwrap(); @@ -178,7 +178,7 @@ mod tests { block_height: 12_345, mix_node: MixNode { identity_key: node_identity.clone(), - ..test_helpers::mix_node_fixture() + ..tests::fixtures::mix_node_fixture() }, profit_margin_percent: None, proxy: None, diff --git a/contracts/mixnet/src/mixnodes/transactions.rs b/contracts/mixnet/src/mixnodes/transactions.rs index fb0f4a2544..81d2c23322 100644 --- a/contracts/mixnet/src/mixnodes/transactions.rs +++ b/contracts/mixnet/src/mixnodes/transactions.rs @@ -231,6 +231,7 @@ pub mod tests { use crate::contract::{execute, query, INITIAL_MIXNODE_PLEDGE}; use crate::error::ContractError; use crate::mixnodes::transactions::validate_mixnode_pledge; + use crate::support::tests; use crate::support::tests::test_helpers; use config::defaults::DENOM; use cosmwasm_std::attr; @@ -248,7 +249,7 @@ pub mod tests { // if we don't send enough funds let insufficient_bond = Into::::into(INITIAL_MIXNODE_PLEDGE) - 1; let info = mock_info("anyone", &coins(insufficient_bond, DENOM)); - let (msg, _) = test_helpers::valid_bond_mixnode_msg("anyone"); + let (msg, _) = tests::messages::valid_bond_mixnode_msg("anyone"); // we are informed that we didn't send enough funds let result = execute(deps.as_mut(), mock_env(), info, msg); @@ -274,8 +275,8 @@ pub mod tests { assert_eq!(0, page.nodes.len()); // if we send enough funds - let info = mock_info("anyone", &test_helpers::good_mixnode_bond()); - let (msg, identity) = test_helpers::valid_bond_mixnode_msg("anyone"); + let info = mock_info("anyone", &tests::fixtures::good_mixnode_pledge()); + let (msg, identity) = tests::messages::valid_bond_mixnode_msg("anyone"); // we get back a message telling us everything was OK let execute_response = execute(deps.as_mut(), mock_env(), info, msg); @@ -296,18 +297,18 @@ pub mod tests { assert_eq!( &MixNode { identity_key: identity, - ..test_helpers::mix_node_fixture() + ..tests::fixtures::mix_node_fixture() }, page.nodes[0].mix_node() ); // if there was already a mixnode bonded by particular user - let info = mock_info("foomper", &test_helpers::good_mixnode_bond()); - let (msg, _) = test_helpers::valid_bond_mixnode_msg("foomper"); + let info = mock_info("foomper", &tests::fixtures::good_mixnode_pledge()); + let (msg, _) = tests::messages::valid_bond_mixnode_msg("foomper"); execute(deps.as_mut(), mock_env(), info, msg).unwrap(); - let info = mock_info("foomper", &test_helpers::good_mixnode_bond()); - let (msg, _) = test_helpers::valid_bond_mixnode_msg("foomper"); + let info = mock_info("foomper", &tests::fixtures::good_mixnode_pledge()); + let (msg, _) = tests::messages::valid_bond_mixnode_msg("foomper"); // it fails let execute_response = execute(deps.as_mut(), mock_env(), info, msg); @@ -316,12 +317,12 @@ pub mod tests { // bonding fails if the user already owns a gateway test_helpers::add_gateway( "gateway-owner", - test_helpers::good_gateway_bond(), + tests::fixtures::good_gateway_pledge(), deps.as_mut(), ); - let info = mock_info("gateway-owner", &test_helpers::good_mixnode_bond()); - let (msg, _) = test_helpers::valid_bond_mixnode_msg("gateway-owner"); + let info = mock_info("gateway-owner", &tests::fixtures::good_mixnode_pledge()); + let (msg, _) = tests::messages::valid_bond_mixnode_msg("gateway-owner"); let execute_response = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(execute_response, Err(ContractError::AlreadyOwnsGateway)); @@ -331,8 +332,8 @@ pub mod tests { let msg = ExecuteMsg::UnbondGateway {}; execute(deps.as_mut(), mock_env(), info, msg).unwrap(); - let info = mock_info("gateway-owner", &test_helpers::good_mixnode_bond()); - let (msg, _) = test_helpers::valid_bond_mixnode_msg("gateway-owner"); + let info = mock_info("gateway-owner", &tests::fixtures::good_mixnode_pledge()); + let (msg, _) = tests::messages::valid_bond_mixnode_msg("gateway-owner"); let execute_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(execute_response.is_ok()); @@ -342,10 +343,10 @@ pub mod tests { } #[test] - fn adding_mixnode_without_existing_owner() { + fn adding_mixnode_without_existing_owner_succeeds() { let mut deps = test_helpers::init_contract(); - let info = mock_info("mix-owner", &test_helpers::good_mixnode_bond()); + let info = mock_info("mix-owner", &tests::fixtures::good_mixnode_pledge()); // before the execution the node had no associated owner assert!(storage::mixnodes() @@ -355,7 +356,7 @@ pub mod tests { .unwrap() .is_none()); - let (msg, identity) = test_helpers::valid_bond_mixnode_msg("mix-owner"); + let (msg, identity) = tests::messages::valid_bond_mixnode_msg("mix-owner"); // it's all fine, owner is saved let execute_response = execute(deps.as_mut(), mock_env(), info, msg); @@ -375,21 +376,24 @@ pub mod tests { } #[test] - fn adding_mixnode_with_existing_owner() { + fn adding_mixnode_with_existing_owner_fails() { let mut deps = test_helpers::init_contract(); let identity = test_helpers::add_mixnode( "mix-owner", - test_helpers::good_mixnode_bond(), + tests::fixtures::good_mixnode_pledge(), deps.as_mut(), ); // request fails giving the existing owner address in the message - let info = mock_info("mix-owner-pretender", &test_helpers::good_mixnode_bond()); + let info = mock_info( + "mix-owner-pretender", + &tests::fixtures::good_mixnode_pledge(), + ); let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: identity, - ..test_helpers::mix_node_fixture() + ..tests::fixtures::mix_node_fixture() }, owner_signature: "foomp".to_string(), }; @@ -404,17 +408,17 @@ pub mod tests { } #[test] - fn adding_mixnode_with_existing_unchanged_owner() { + fn adding_mixnode_with_existing_unchanged_owner_fails() { let mut deps = test_helpers::init_contract(); test_helpers::add_mixnode( "mix-owner", - test_helpers::good_mixnode_bond(), + tests::fixtures::good_mixnode_pledge(), deps.as_mut(), ); - let info = mock_info("mix-owner", &test_helpers::good_mixnode_bond()); - let (msg, _) = test_helpers::valid_bond_mixnode_msg("mix-owner"); + let info = mock_info("mix-owner", &tests::fixtures::good_mixnode_pledge()); + let (msg, _) = tests::messages::valid_bond_mixnode_msg("mix-owner"); let res = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(Err(ContractError::AlreadyOwnsMixnode), res); @@ -429,7 +433,11 @@ pub mod tests { mixnet_params_storage::LAYERS.load(&deps.storage).unwrap(), ); - test_helpers::add_mixnode("mix1", test_helpers::good_mixnode_bond(), deps.as_mut()); + test_helpers::add_mixnode( + "mix1", + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); assert_eq!( LayerDistribution { @@ -458,7 +466,7 @@ pub mod tests { ); // let's add a node owned by bob - test_helpers::add_mixnode("bob", test_helpers::good_mixnode_bond(), deps.as_mut()); + test_helpers::add_mixnode("bob", tests::fixtures::good_mixnode_pledge(), deps.as_mut()); // attempt to un-register fred's node, which doesn't exist let info = mock_info("fred", &[]); @@ -472,16 +480,19 @@ pub mod tests { ); // bob's node is still there - let nodes = test_helpers::get_mix_nodes(&mut deps); + let nodes = tests::queries::get_mix_nodes(&mut deps); assert_eq!(1, nodes.len()); assert_eq!("bob", nodes[0].owner().clone()); // add a node owned by fred - let fred_identity = - test_helpers::add_mixnode("fred", test_helpers::good_mixnode_bond(), deps.as_mut()); + let fred_identity = test_helpers::add_mixnode( + "fred", + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); // let's make sure we now have 2 nodes: - assert_eq!(2, test_helpers::get_mix_nodes(&mut deps).len()); + assert_eq!(2, tests::queries::get_mix_nodes(&mut deps).len()); // un-register fred's node let info = mock_info("fred", &[]); @@ -503,7 +514,7 @@ pub mod tests { // we should see a funds transfer from the contract back to fred let expected_message = BankMsg::Send { to_address: String::from(info.sender), - amount: test_helpers::good_mixnode_bond(), + amount: tests::fixtures::good_mixnode_pledge(), }; // run the executor and check that we got back the correct results @@ -514,7 +525,7 @@ pub mod tests { assert_eq!(remove_fred, expected); // only 1 node now exists, owned by bob: - let mix_node_bonds = test_helpers::get_mix_nodes(&mut deps); + let mix_node_bonds = tests::queries::get_mix_nodes(&mut deps); assert_eq!(1, mix_node_bonds.len()); assert_eq!(&Addr::unchecked("bob"), mix_node_bonds[0].owner()); } @@ -523,8 +534,8 @@ pub mod tests { fn removing_mixnode_clears_ownership() { let mut deps = test_helpers::init_contract(); - let info = mock_info("mix-owner", &test_helpers::good_mixnode_bond()); - let (bond_msg, identity) = test_helpers::valid_bond_mixnode_msg("mix-owner"); + let info = mock_info("mix-owner", &tests::fixtures::good_mixnode_pledge()); + let (bond_msg, identity) = tests::messages::valid_bond_mixnode_msg("mix-owner"); execute(deps.as_mut(), mock_env(), info, bond_msg.clone()).unwrap(); assert_eq!( @@ -552,7 +563,7 @@ pub mod tests { .is_none()); // and since it's removed, it can be reclaimed - let info = mock_info("mix-owner", &test_helpers::good_mixnode_bond()); + let info = mock_info("mix-owner", &tests::fixtures::good_mixnode_pledge()); assert!(execute(deps.as_mut(), mock_env(), info, bond_msg).is_ok()); assert_eq!( @@ -575,7 +586,7 @@ pub mod tests { assert_eq!(result, Err(ContractError::NoBondFound)); // you must send at least 100 coins... - let mut bond = test_helpers::good_mixnode_bond(); + let mut bond = tests::fixtures::good_mixnode_pledge(); bond[0].amount = INITIAL_MIXNODE_PLEDGE.checked_sub(Uint128::new(1)).unwrap(); let result = validate_mixnode_pledge(bond.clone(), INITIAL_MIXNODE_PLEDGE); assert_eq!( @@ -587,32 +598,48 @@ pub mod tests { ); // more than that is still fine - let mut bond = test_helpers::good_mixnode_bond(); + let mut bond = tests::fixtures::good_mixnode_pledge(); bond[0].amount = INITIAL_MIXNODE_PLEDGE + Uint128::new(1); let result = validate_mixnode_pledge(bond.clone(), INITIAL_MIXNODE_PLEDGE); assert!(result.is_ok()); // it must be sent in the defined denom! - let mut bond = test_helpers::good_mixnode_bond(); + let mut bond = tests::fixtures::good_mixnode_pledge(); bond[0].denom = "baddenom".to_string(); let result = validate_mixnode_pledge(bond.clone(), INITIAL_MIXNODE_PLEDGE); assert_eq!(result, Err(ContractError::WrongDenom {})); - let mut bond = test_helpers::good_mixnode_bond(); + let mut bond = tests::fixtures::good_mixnode_pledge(); bond[0].denom = "foomp".to_string(); let result = validate_mixnode_pledge(bond.clone(), INITIAL_MIXNODE_PLEDGE); assert_eq!(result, Err(ContractError::WrongDenom {})); } + #[cfg(test)] + mod owner_signature { + // use super::*; + + #[test] + fn bonding_a_mixnode_with_a_correct_owner_signature() { + // the owner signature here matches the wallet address via the mixnode's self-declared public key + // let sender = "nymt1m44hu9wguv5gx3p0estfzsnjkrjluu83y7chyf"; + // let (owner_signature, public_key) = crate::support::tests::signing::sign(sender); + // let mut bond_message = tests::messages::valid_bond_mixnode_msg(sender); + } + } + #[test] fn choose_layer_mix_node() { let mut deps = test_helpers::init_contract(); - let alice_identity = - test_helpers::add_mixnode("alice", test_helpers::good_mixnode_bond(), deps.as_mut()); + let alice_identity = test_helpers::add_mixnode( + "alice", + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); let bob_identity = - test_helpers::add_mixnode("bob", test_helpers::good_mixnode_bond(), deps.as_mut()); + test_helpers::add_mixnode("bob", tests::fixtures::good_mixnode_pledge(), deps.as_mut()); - let bonded_mix_nodes = test_helpers::get_mix_nodes(&mut deps); + let bonded_mix_nodes = tests::queries::get_mix_nodes(&mut deps); let alice_node = bonded_mix_nodes .iter() .find(|m| m.owner == "alice") diff --git a/contracts/mixnet/src/rewards/queries.rs b/contracts/mixnet/src/rewards/queries.rs index dd57235b14..7d643c073d 100644 --- a/contracts/mixnet/src/rewards/queries.rs +++ b/contracts/mixnet/src/rewards/queries.rs @@ -31,6 +31,7 @@ pub(crate) fn query_rewarding_status( pub(crate) mod tests { use super::*; use crate::mixnet_contract_settings::storage as mixnet_params_storage; + use crate::support::tests; use crate::support::tests::test_helpers; use cosmwasm_std::testing::{mock_env, mock_info}; @@ -56,8 +57,11 @@ pub(crate) mod tests { .unwrap(); let rewarding_validator_address = current_state.rewarding_validator_address; - let node_identity = - test_helpers::add_mixnode("bob", test_helpers::good_mixnode_bond(), deps.as_mut()); + let node_identity = test_helpers::add_mixnode( + "bob", + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); assert!( query_rewarding_status(deps.as_ref(), node_identity.clone(), 1) @@ -74,7 +78,7 @@ pub(crate) mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -99,7 +103,7 @@ pub(crate) mod tests { let node_owner: Addr = Addr::unchecked("bob"); let node_identity = test_helpers::add_mixnode( node_owner.as_str(), - test_helpers::good_mixnode_bond(), + tests::fixtures::good_mixnode_pledge(), deps.as_mut(), ); @@ -112,7 +116,7 @@ pub(crate) mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -139,7 +143,7 @@ pub(crate) mod tests { let node_owner: Addr = Addr::unchecked("alice"); let node_identity = test_helpers::add_mixnode( node_owner.as_str(), - test_helpers::good_mixnode_bond(), + tests::fixtures::good_mixnode_pledge(), deps.as_mut(), ); @@ -166,7 +170,7 @@ pub(crate) mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 2, ) .unwrap(); @@ -210,7 +214,7 @@ pub(crate) mod tests { let node_owner: Addr = Addr::unchecked("bob"); let node_identity = test_helpers::add_mixnode( node_owner.as_str(), - test_helpers::good_mixnode_bond(), + tests::fixtures::good_mixnode_pledge(), deps.as_mut(), ); @@ -237,7 +241,7 @@ pub(crate) mod tests { env.clone(), info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index f8aa79a9aa..7457f0e3ed 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -389,8 +389,8 @@ pub mod tests { use crate::rewards::transactions::{ try_begin_mixnode_rewarding, try_finish_mixnode_rewarding, try_reward_mixnode, }; + use crate::support::tests; use crate::support::tests::test_helpers; - use crate::support::tests::test_helpers::{good_mixnode_bond, mix_node_fixture}; use config::defaults::DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::Coin; @@ -753,8 +753,11 @@ pub mod tests { // bond the node let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity = - test_helpers::add_mixnode(node_owner.as_str(), good_mixnode_bond(), deps.as_mut()); + let node_identity = test_helpers::add_mixnode( + node_owner.as_str(), + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); let info = mock_info(rewarding_validator_address.as_ref(), &[]); let res = try_reward_mixnode( @@ -762,7 +765,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ); assert_eq!(Err(ContractError::RewardingNotInProgress), res); @@ -774,7 +777,7 @@ pub mod tests { env.clone(), info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ); assert!(res.is_ok()) @@ -791,8 +794,11 @@ pub mod tests { // bond the node let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity = - test_helpers::add_mixnode(node_owner.as_str(), good_mixnode_bond(), deps.as_mut()); + let node_identity = test_helpers::add_mixnode( + node_owner.as_str(), + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); let info = mock_info(rewarding_validator_address.as_ref(), &[]); try_begin_mixnode_rewarding(deps.as_mut(), env.clone(), info.clone(), 1).unwrap(); @@ -801,7 +807,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 0, ); assert_eq!( @@ -817,7 +823,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 2, ); assert_eq!( @@ -833,7 +839,7 @@ pub mod tests { env.clone(), info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ); assert!(res.is_ok()) @@ -850,8 +856,11 @@ pub mod tests { // bond the node let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity = - test_helpers::add_mixnode(node_owner.as_str(), good_mixnode_bond(), deps.as_mut()); + let node_identity = test_helpers::add_mixnode( + node_owner.as_str(), + tests::fixtures::good_mixnode_pledge(), + deps.as_mut(), + ); let info = mock_info(rewarding_validator_address.as_ref(), &[]); try_begin_mixnode_rewarding(deps.as_mut(), env.clone(), info.clone(), 1).unwrap(); @@ -862,7 +871,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ); assert!(res.is_ok()); @@ -873,7 +882,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ); assert_eq!( @@ -892,7 +901,7 @@ pub mod tests { env, info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 2, ); assert!(res.is_ok()); @@ -919,7 +928,7 @@ pub mod tests { block_height: env.block.height, mix_node: MixNode { identity_key: node_identity.clone(), - ..mix_node_fixture() + ..tests::fixtures::mix_node_fixture() }, profit_margin_percent: Some(10), proxy: None, @@ -960,7 +969,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -998,7 +1007,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 2, ) .unwrap(); @@ -1041,7 +1050,7 @@ pub mod tests { env.clone(), info.clone(), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 3, ) .unwrap(); @@ -1277,7 +1286,7 @@ pub mod tests { env, info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -1358,7 +1367,7 @@ pub mod tests { env, info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -1439,7 +1448,7 @@ pub mod tests { env, info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -1511,7 +1520,7 @@ pub mod tests { } env.block.height += storage::MINIMUM_BLOCK_AGE_FOR_REWARDING + 1; - let mut node_rewarding_params = test_helpers::node_rewarding_params_fixture(100); + let mut node_rewarding_params = tests::fixtures::node_rewarding_params_fixture(100); node_rewarding_params.set_reward_blockstamp(env.block.height); let params = DelegatorRewardParams::new(&bond, node_rewarding_params); @@ -1564,7 +1573,7 @@ pub mod tests { } env.block.height += storage::MINIMUM_BLOCK_AGE_FOR_REWARDING + 1; - let mut node_rewarding_params = test_helpers::node_rewarding_params_fixture(100); + let mut node_rewarding_params = tests::fixtures::node_rewarding_params_fixture(100); node_rewarding_params.set_reward_blockstamp(env.block.height); let params = DelegatorRewardParams::new(&bond, node_rewarding_params); @@ -1730,7 +1739,7 @@ pub mod tests { env.clone(), mock_info(rewarding_validator_address.as_ref(), &[]), node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -1793,7 +1802,7 @@ pub mod tests { env.clone(), info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 2, ) .unwrap(); @@ -1883,7 +1892,7 @@ pub mod tests { env.clone(), info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); @@ -2002,7 +2011,7 @@ pub mod tests { env.clone(), info, node_identity.clone(), - test_helpers::node_rewarding_params_fixture(100), + tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); diff --git a/contracts/mixnet/src/support/tests.rs b/contracts/mixnet/src/support/tests.rs deleted file mode 100644 index b5f86aa2e1..0000000000 --- a/contracts/mixnet/src/support/tests.rs +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2021 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -#[cfg(test)] -pub mod test_helpers { - use super::*; - use crate::contract::{instantiate, INITIAL_MIXNODE_PLEDGE}; - use crate::contract::{ - query, DEFAULT_SYBIL_RESISTANCE_PERCENT, EPOCH_REWARD_PERCENT, INITIAL_REWARD_POOL, - }; - use crate::delegations::storage as delegations_storage; - use crate::gateways::transactions::try_add_gateway; - use crate::mixnodes::storage as mixnodes_storage; - use crate::mixnodes::storage::StoredMixnodeBond; - use crate::mixnodes::transactions::try_add_mixnode; - use config::defaults::{DENOM, TOTAL_SUPPLY}; - use cosmwasm_std::coin; - use cosmwasm_std::testing::mock_dependencies; - use cosmwasm_std::testing::mock_env; - use cosmwasm_std::testing::mock_info; - use cosmwasm_std::testing::MockApi; - use cosmwasm_std::testing::MockQuerier; - use cosmwasm_std::testing::MockStorage; - use cosmwasm_std::Coin; - use cosmwasm_std::OwnedDeps; - use cosmwasm_std::{from_binary, DepsMut}; - use cosmwasm_std::{Addr, StdResult, Storage}; - use cosmwasm_std::{Empty, MemoryStorage}; - use cw_storage_plus::PrimaryKey; - use mixnet_contract::mixnode::NodeRewardParams; - use mixnet_contract::{ - Delegation, ExecuteMsg, Gateway, GatewayBond, IdentityKey, IdentityKeyRef, InstantiateMsg, - Layer, MixNode, MixNodeBond, PagedGatewayResponse, PagedMixnodeResponse, QueryMsg, - }; - use rand::thread_rng; - - pub(crate) fn valid_bond_mixnode_msg(sender: &str) -> (ExecuteMsg, IdentityKey) { - let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); - let owner_signature = keypair - .private_key() - .sign(sender.as_bytes()) - .to_base58_string(); - - let identity_key = keypair.public_key().to_base58_string(); - ( - ExecuteMsg::BondMixnode { - mix_node: MixNode { - identity_key: identity_key.clone(), - ..test_helpers::mix_node_fixture() - }, - owner_signature, - }, - identity_key, - ) - } - - pub fn add_mixnode(sender: &str, stake: Vec, deps: DepsMut) -> String { - let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); - let owner_signature = keypair - .private_key() - .sign(sender.as_bytes()) - .to_base58_string(); - - let info = mock_info(sender, &stake); - let key = keypair.public_key().to_base58_string(); - - try_add_mixnode( - deps, - mock_env(), - info, - MixNode { - identity_key: key.clone(), - ..test_helpers::mix_node_fixture() - }, - owner_signature, - ) - .unwrap(); - key - } - - pub fn get_mix_nodes( - deps: &mut OwnedDeps, - ) -> Vec { - let result = query( - deps.as_ref(), - mock_env(), - QueryMsg::GetMixNodes { - start_after: None, - limit: Option::from(2), - }, - ) - .unwrap(); - - let page: PagedMixnodeResponse = from_binary(&result).unwrap(); - page.nodes - } - - pub(crate) fn valid_bond_gateway_msg(sender: &str) -> (ExecuteMsg, IdentityKey) { - let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); - let owner_signature = keypair - .private_key() - .sign(sender.as_bytes()) - .to_base58_string(); - - let identity_key = keypair.public_key().to_base58_string(); - ( - ExecuteMsg::BondGateway { - gateway: Gateway { - identity_key: identity_key.clone(), - ..test_helpers::gateway_fixture() - }, - owner_signature, - }, - identity_key, - ) - } - - pub fn add_gateway(sender: &str, stake: Vec, deps: DepsMut) -> String { - let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); - let owner_signature = keypair - .private_key() - .sign(sender.as_bytes()) - .to_base58_string(); - - let info = mock_info(sender, &stake); - let key = keypair.public_key().to_base58_string(); - try_add_gateway( - deps, - mock_env(), - info, - Gateway { - identity_key: key.clone(), - ..test_helpers::gateway_fixture() - }, - owner_signature, - ) - .unwrap(); - key - } - - pub fn get_gateways( - deps: &mut OwnedDeps, - ) -> Vec { - let result = query( - deps.as_ref(), - mock_env(), - QueryMsg::GetGateways { - start_after: None, - limit: None, - }, - ) - .unwrap(); - - let page: PagedGatewayResponse = from_binary(&result).unwrap(); - page.nodes - } - - pub fn init_contract() -> OwnedDeps> { - let mut deps = mock_dependencies(); - let msg = InstantiateMsg { - rewarding_validator_address: config::defaults::REWARDING_VALIDATOR_ADDRESS.to_string(), - }; - let env = mock_env(); - let info = mock_info("creator", &[]); - instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); - deps - } - - pub fn mix_node_fixture() -> MixNode { - MixNode { - host: "mix.node.org".to_string(), - mix_port: 1789, - verloc_port: 1790, - http_api_port: 8000, - sphinx_key: "sphinx".to_string(), - identity_key: "identity".to_string(), - version: "0.10.0".to_string(), - profit_margin_percent: 10, - } - } - - pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::StoredMixnodeBond { - StoredMixnodeBond::new( - coin(50, DENOM), - Addr::unchecked(owner), - Layer::One, - 12_345, - MixNode { - identity_key: format!("id-{}", owner), - ..mix_node_fixture() - }, - None, - None, - ) - } - - pub fn gateway_fixture() -> Gateway { - Gateway { - host: "1.1.1.1".to_string(), - mix_port: 1789, - clients_port: 9000, - location: "Sweden".to_string(), - sphinx_key: "sphinx".to_string(), - identity_key: "identity".to_string(), - version: "0.10.0".to_string(), - } - } - - pub fn gateway_bond_fixture(owner: &str) -> GatewayBond { - let gateway = Gateway { - identity_key: format!("id-{}", owner), - ..gateway_fixture() - }; - GatewayBond::new( - coin(50, DENOM), - Addr::unchecked(owner), - 12_345, - gateway, - None, - ) - } - - pub fn query_contract_balance( - address: Addr, - deps: OwnedDeps, - ) -> Vec { - let querier = deps.as_ref().querier; - vec![querier.query_balance(address, DENOM).unwrap()] - } - - pub fn good_mixnode_bond() -> Vec { - vec![Coin { - denom: DENOM.to_string(), - amount: INITIAL_MIXNODE_PLEDGE, - }] - } - - pub fn good_gateway_bond() -> Vec { - vec![Coin { - denom: DENOM.to_string(), - amount: INITIAL_MIXNODE_PLEDGE, - }] - } - - // when exact values are irrelevant and what matters is the action of rewarding - pub fn node_rewarding_params_fixture(uptime: u128) -> NodeRewardParams { - NodeRewardParams::new( - (INITIAL_REWARD_POOL / 100) * EPOCH_REWARD_PERCENT as u128, - 50 as u128, - 25 as u128, - 0, - TOTAL_SUPPLY - INITIAL_REWARD_POOL, - uptime, - DEFAULT_SYBIL_RESISTANCE_PERCENT, - true, - 10, - ) - } - - // currently not used outside tests - pub(crate) fn read_mixnode_pledge_amount( - storage: &dyn Storage, - identity: IdentityKeyRef, - ) -> StdResult { - let node = mixnodes_storage::mixnodes().load(storage, identity)?; - Ok(node.pledge_amount.amount) - } - - pub(crate) fn save_dummy_delegation( - storage: &mut dyn Storage, - mix: impl Into, - owner: impl Into, - ) { - let delegation = Delegation { - owner: Addr::unchecked(owner.into()), - node_identity: mix.into(), - amount: coin(12345, DENOM), - block_height: 12345, - proxy: None, - }; - - delegations_storage::delegations() - .save(storage, delegation.storage_key().joined_key(), &delegation) - .unwrap(); - } - - pub(crate) fn read_delegation( - storage: &dyn Storage, - mix: impl Into, - owner: impl Into, - ) -> Option { - delegations_storage::delegations() - .may_load(storage, (mix.into(), owner.into()).joined_key()) - .unwrap() - } -} diff --git a/contracts/mixnet/src/support/tests/fixtures.rs b/contracts/mixnet/src/support/tests/fixtures.rs new file mode 100644 index 0000000000..af4f6ab14f --- /dev/null +++ b/contracts/mixnet/src/support/tests/fixtures.rs @@ -0,0 +1,93 @@ +use crate::contract::{ + DEFAULT_SYBIL_RESISTANCE_PERCENT, EPOCH_REWARD_PERCENT, INITIAL_MIXNODE_PLEDGE, + INITIAL_REWARD_POOL, +}; +use crate::mixnodes::storage as mixnodes_storage; +use crate::{mixnodes::storage::StoredMixnodeBond, support::tests}; +use config::defaults::{DENOM, TOTAL_SUPPLY}; +use cosmwasm_std::{coin, Addr, Coin}; +use mixnet_contract::mixnode::NodeRewardParams; +use mixnet_contract::{Gateway, GatewayBond, Layer, MixNode}; + +pub fn mix_node_fixture() -> MixNode { + MixNode { + host: "mix.node.org".to_string(), + mix_port: 1789, + verloc_port: 1790, + http_api_port: 8000, + sphinx_key: "sphinx".to_string(), + identity_key: "identity".to_string(), + version: "0.10.0".to_string(), + profit_margin_percent: 10, + } +} + +pub fn gateway_fixture() -> Gateway { + Gateway { + host: "1.1.1.1".to_string(), + mix_port: 1789, + clients_port: 9000, + location: "Sweden".to_string(), + sphinx_key: "sphinx".to_string(), + identity_key: "identity".to_string(), + version: "0.10.0".to_string(), + } +} + +pub fn gateway_bond_fixture(owner: &str) -> GatewayBond { + let gateway = Gateway { + identity_key: format!("id-{}", owner), + ..tests::fixtures::gateway_fixture() + }; + GatewayBond::new( + coin(50, DENOM), + Addr::unchecked(owner), + 12_345, + gateway, + None, + ) +} + +pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::StoredMixnodeBond { + StoredMixnodeBond::new( + coin(50, DENOM), + Addr::unchecked(owner), + Layer::One, + 12_345, + MixNode { + identity_key: format!("id-{}", owner), + ..super::fixtures::mix_node_fixture() + }, + None, + None, + ) +} + +pub fn good_mixnode_pledge() -> Vec { + vec![Coin { + denom: DENOM.to_string(), + amount: INITIAL_MIXNODE_PLEDGE, + }] +} + +pub fn good_gateway_pledge() -> Vec { + vec![Coin { + denom: DENOM.to_string(), + amount: INITIAL_MIXNODE_PLEDGE, + }] +} + +// when exact values are irrelevant and what matters is the action of rewarding +pub fn node_rewarding_params_fixture(uptime: u128) -> NodeRewardParams { + NodeRewardParams::new( + (INITIAL_REWARD_POOL / 100) * EPOCH_REWARD_PERCENT as u128, + 50 as u128, + 25 as u128, + 0, + TOTAL_SUPPLY - INITIAL_REWARD_POOL, + uptime, + DEFAULT_SYBIL_RESISTANCE_PERCENT, + true, + 10, + ) +} diff --git a/contracts/mixnet/src/support/tests/messages.rs b/contracts/mixnet/src/support/tests/messages.rs new file mode 100644 index 0000000000..e7f8af7a91 --- /dev/null +++ b/contracts/mixnet/src/support/tests/messages.rs @@ -0,0 +1,44 @@ +use mixnet_contract::{ExecuteMsg, Gateway, IdentityKey, MixNode}; +use rand::thread_rng; + +use crate::support::tests; + +pub(crate) fn valid_bond_mixnode_msg(sender: &str) -> (ExecuteMsg, IdentityKey) { + let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); + let owner_signature = keypair + .private_key() + .sign(sender.as_bytes()) + .to_base58_string(); + + let identity_key = keypair.public_key().to_base58_string(); + ( + ExecuteMsg::BondMixnode { + mix_node: MixNode { + identity_key: identity_key.clone(), + ..tests::fixtures::mix_node_fixture() + }, + owner_signature, + }, + identity_key, + ) +} + +pub(crate) fn valid_bond_gateway_msg(sender: &str) -> (ExecuteMsg, IdentityKey) { + let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); + let owner_signature = keypair + .private_key() + .sign(sender.as_bytes()) + .to_base58_string(); + + let identity_key = keypair.public_key().to_base58_string(); + ( + ExecuteMsg::BondGateway { + gateway: Gateway { + identity_key: identity_key.clone(), + ..tests::fixtures::gateway_fixture() + }, + owner_signature, + }, + identity_key, + ) +} diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs new file mode 100644 index 0000000000..d8b1909415 --- /dev/null +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -0,0 +1,130 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 +#[cfg(test)] +pub mod fixtures; +#[cfg(test)] +pub mod messages; +#[cfg(test)] +pub mod queries; +#[cfg(test)] +pub mod signing; + +#[cfg(test)] +pub mod test_helpers { + use crate::contract::instantiate; + use crate::delegations::storage as delegations_storage; + use crate::gateways::transactions::try_add_gateway; + use crate::mixnodes::storage as mixnodes_storage; + use crate::mixnodes::transactions::try_add_mixnode; + use crate::support::tests; + use config::defaults::DENOM; + use cosmwasm_std::coin; + use cosmwasm_std::testing::mock_dependencies; + use cosmwasm_std::testing::mock_env; + use cosmwasm_std::testing::mock_info; + use cosmwasm_std::testing::MockApi; + use cosmwasm_std::testing::MockQuerier; + use cosmwasm_std::Coin; + use cosmwasm_std::DepsMut; + use cosmwasm_std::OwnedDeps; + use cosmwasm_std::{Addr, StdResult, Storage}; + use cosmwasm_std::{Empty, MemoryStorage}; + use cw_storage_plus::PrimaryKey; + use mixnet_contract::{Delegation, Gateway, IdentityKeyRef, InstantiateMsg, MixNode}; + use rand::thread_rng; + + pub fn add_mixnode(sender: &str, stake: Vec, deps: DepsMut) -> String { + let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); + let owner_signature = keypair + .private_key() + .sign(sender.as_bytes()) + .to_base58_string(); + + let info = mock_info(sender, &stake); + let key = keypair.public_key().to_base58_string(); + + try_add_mixnode( + deps, + mock_env(), + info, + MixNode { + identity_key: key.clone(), + ..tests::fixtures::mix_node_fixture() + }, + owner_signature, + ) + .unwrap(); + key + } + + pub fn add_gateway(sender: &str, stake: Vec, deps: DepsMut) -> String { + let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); + let owner_signature = keypair + .private_key() + .sign(sender.as_bytes()) + .to_base58_string(); + + let info = mock_info(sender, &stake); + let key = keypair.public_key().to_base58_string(); + try_add_gateway( + deps, + mock_env(), + info, + Gateway { + identity_key: key.clone(), + ..tests::fixtures::gateway_fixture() + }, + owner_signature, + ) + .unwrap(); + key + } + + pub fn init_contract() -> OwnedDeps> { + let mut deps = mock_dependencies(); + let msg = InstantiateMsg { + rewarding_validator_address: config::defaults::REWARDING_VALIDATOR_ADDRESS.to_string(), + }; + let env = mock_env(); + let info = mock_info("creator", &[]); + instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); + deps + } + + // currently not used outside tests + pub(crate) fn read_mixnode_pledge_amount( + storage: &dyn Storage, + identity: IdentityKeyRef, + ) -> StdResult { + let node = mixnodes_storage::mixnodes().load(storage, identity)?; + Ok(node.pledge_amount.amount) + } + + pub(crate) fn save_dummy_delegation( + storage: &mut dyn Storage, + mix: impl Into, + owner: impl Into, + ) { + let delegation = Delegation { + owner: Addr::unchecked(owner.into()), + node_identity: mix.into(), + amount: coin(12345, DENOM), + block_height: 12345, + proxy: None, + }; + + delegations_storage::delegations() + .save(storage, delegation.storage_key().joined_key(), &delegation) + .unwrap(); + } + + pub(crate) fn read_delegation( + storage: &dyn Storage, + mix: impl Into, + owner: impl Into, + ) -> Option { + delegations_storage::delegations() + .may_load(storage, (mix.into(), owner.into()).joined_key()) + .unwrap() + } +} diff --git a/contracts/mixnet/src/support/tests/queries.rs b/contracts/mixnet/src/support/tests/queries.rs new file mode 100644 index 0000000000..4c8d00195e --- /dev/null +++ b/contracts/mixnet/src/support/tests/queries.rs @@ -0,0 +1,49 @@ +use config::defaults::DENOM; +use cosmwasm_std::{ + from_binary, + testing::{mock_env, MockApi, MockQuerier, MockStorage}, + Addr, Coin, OwnedDeps, +}; +use mixnet_contract::{ + GatewayBond, MixNodeBond, PagedGatewayResponse, PagedMixnodeResponse, QueryMsg, +}; + +use crate::contract::query; + +pub fn get_mix_nodes(deps: &mut OwnedDeps) -> Vec { + let result = query( + deps.as_ref(), + mock_env(), + QueryMsg::GetMixNodes { + start_after: None, + limit: Option::from(2), + }, + ) + .unwrap(); + + let page: PagedMixnodeResponse = from_binary(&result).unwrap(); + page.nodes +} + +pub fn get_gateways(deps: &mut OwnedDeps) -> Vec { + let result = query( + deps.as_ref(), + mock_env(), + QueryMsg::GetGateways { + start_after: None, + limit: None, + }, + ) + .unwrap(); + + let page: PagedGatewayResponse = from_binary(&result).unwrap(); + page.nodes +} + +pub fn query_contract_balance( + address: Addr, + deps: OwnedDeps, +) -> Vec { + let querier = deps.as_ref().querier; + vec![querier.query_balance(address, DENOM).unwrap()] +} diff --git a/contracts/mixnet/src/support/tests/signing.rs b/contracts/mixnet/src/support/tests/signing.rs new file mode 100644 index 0000000000..8650e233d3 --- /dev/null +++ b/contracts/mixnet/src/support/tests/signing.rs @@ -0,0 +1,14 @@ +// use ed25519_dalek::{Keypair, PublicKey, Signature, Signer}; + +// use rand::rngs::OsRng; + +// /// A test helper which signs a piece of text with a supplied private key +// /// This is test-only code, not meant for use inside the smart contract. +// /// It allows us to sign things so we can test that verification works inside +// /// the smart contract. +// pub(crate) fn sign(text: &str) -> (Signature, PublicKey) { +// let mut csprng = OsRng {}; +// let keypair: Keypair = Keypair::generate(&mut csprng); +// let signature: Signature = keypair.sign(text.as_bytes()); +// (signature, keypair.public) +// }