Added contract query to check if given address owns a mixnode/gateway (#544)

* Added contract query to check if given address owns a mixnode/gateway

* Fixed merge conflict
This commit is contained in:
Jędrzej Stuczyński
2021-03-24 17:29:08 +00:00
committed by GitHub
parent 52d4ddb714
commit 7361d7a220
6 changed files with 117 additions and 5 deletions
+6
View File
@@ -109,3 +109,9 @@ impl PagedGatewayResponse {
}
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct GatewayOwnershipResponse {
pub address: HumanAddr,
pub has_gateway: bool,
}
+2 -2
View File
@@ -2,5 +2,5 @@ mod gateway;
mod mixnode;
pub use cosmwasm_std::{Coin, HumanAddr};
pub use gateway::{Gateway, GatewayBond, PagedGatewayResponse};
pub use mixnode::{MixNode, MixNodeBond, PagedResponse};
pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse};
pub use mixnode::{MixNode, MixNodeBond, MixOwnershipResponse, PagedResponse};
+6
View File
@@ -105,3 +105,9 @@ impl PagedResponse {
}
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct MixOwnershipResponse {
pub address: HumanAddr,
pub has_node: bool,
}
+5 -1
View File
@@ -1,5 +1,7 @@
use crate::msg::{HandleMsg, InitMsg, QueryMsg};
use crate::queries::{query_gateways_paged, query_mixnodes_paged};
use crate::queries::{
query_gateways_paged, query_mixnodes_paged, query_owns_gateway, query_owns_mixnode,
};
use crate::state::{config, gateways, gateways_read, State};
use crate::{error::ContractError, state::mixnodes, state::mixnodes_read};
use cosmwasm_std::{
@@ -200,6 +202,8 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
QueryMsg::GetGateways { limit, start_after } => {
to_binary(&query_gateways_paged(deps, start_after, limit)?)
}
QueryMsg::OwnsMixnode { address } => to_binary(&query_owns_mixnode(deps, address)?),
QueryMsg::OwnsGateway { address } => to_binary(&query_owns_gateway(deps, address)?),
}
}
+6
View File
@@ -26,4 +26,10 @@ pub enum QueryMsg {
start_after: Option<HumanAddr>,
limit: Option<u32>,
},
OwnsMixnode {
address: HumanAddr,
},
OwnsGateway {
address: HumanAddr,
},
}
+92 -2
View File
@@ -1,11 +1,14 @@
// settings for pagination
use crate::state::{gateways_read, PREFIX_MIXNODES};
use crate::state::{gateways_read, mixnodes_read, PREFIX_MIXNODES};
use cosmwasm_std::Deps;
use cosmwasm_std::HumanAddr;
use cosmwasm_std::Order;
use cosmwasm_std::StdResult;
use cosmwasm_storage::bucket_read;
use mixnet_contract::{GatewayBond, MixNodeBond, PagedGatewayResponse, PagedResponse};
use mixnet_contract::{
GatewayBond, GatewayOwnershipResponse, MixNodeBond, MixOwnershipResponse, PagedGatewayResponse,
PagedResponse,
};
const MAX_LIMIT: u32 = 30;
const DEFAULT_LIMIT: u32 = 10;
@@ -52,6 +55,29 @@ pub(crate) fn query_gateways_paged(
Ok(PagedGatewayResponse::new(nodes, limit, start_next_after))
}
pub(crate) fn query_owns_mixnode(
deps: Deps,
address: HumanAddr,
) -> StdResult<MixOwnershipResponse> {
let has_node = mixnodes_read(deps.storage)
.may_load(address.as_ref())?
.is_some();
Ok(MixOwnershipResponse { address, has_node })
}
pub(crate) fn query_owns_gateway(
deps: Deps,
address: HumanAddr,
) -> StdResult<GatewayOwnershipResponse> {
let has_gateway = gateways_read(deps.storage)
.may_load(address.as_ref())?
.is_some();
Ok(GatewayOwnershipResponse {
address,
has_gateway,
})
}
/// Adds a 0 byte to terminate the `start_after` value given. This allows CosmWasm
/// to get the succeeding key as the start of the next page.
fn calculate_start_value(
@@ -306,4 +332,68 @@ mod tests {
// now we have 2 pages, with 2 results on the second page
assert_eq!(2, page2.nodes.len());
}
#[test]
fn query_for_mixnode_owner_works() {
let mut deps = helpers::init_contract();
// "fred" does not own a mixnode if there are no mixnodes
let res = query_owns_mixnode(deps.as_ref(), "fred".into()).unwrap();
assert!(!res.has_node);
// mixnode was added to "bob", "fred" still does not own one
let node = helpers::mixnode_bond_fixture();
mixnodes(&mut deps.storage)
.save("bob".as_bytes(), &node)
.unwrap();
let res = query_owns_mixnode(deps.as_ref(), "fred".into()).unwrap();
assert!(!res.has_node);
// "fred" now owns a mixnode!
let node2 = helpers::mixnode_bond_fixture();
mixnodes(&mut deps.storage)
.save("fred".as_bytes(), &node2)
.unwrap();
let res = query_owns_mixnode(deps.as_ref(), "fred".into()).unwrap();
assert!(res.has_node);
// but after unbonding it, he doesn't own one anymore
mixnodes(&mut deps.storage).remove("fred".as_bytes());
let res = query_owns_mixnode(deps.as_ref(), "fred".into()).unwrap();
assert!(!res.has_node);
}
#[test]
fn query_for_gateway_owner_works() {
let mut deps = helpers::init_contract();
// "fred" does not own a mixnode if there are no mixnodes
let res = query_owns_gateway(deps.as_ref(), "fred".into()).unwrap();
assert!(!res.has_gateway);
// mixnode was added to "bob", "fred" still does not own one
let node = helpers::gateway_bond_fixture();
gateways(&mut deps.storage)
.save("bob".as_bytes(), &node)
.unwrap();
let res = query_owns_gateway(deps.as_ref(), "fred".into()).unwrap();
assert!(!res.has_gateway);
// "fred" now owns a mixnode!
let node2 = helpers::gateway_bond_fixture();
gateways(&mut deps.storage)
.save("fred".as_bytes(), &node2)
.unwrap();
let res = query_owns_gateway(deps.as_ref(), "fred".into()).unwrap();
assert!(res.has_gateway);
// but after unbonding it, he doesn't own one anymore
gateways(&mut deps.storage).remove("fred".as_bytes());
let res = query_owns_gateway(deps.as_ref(), "fred".into()).unwrap();
assert!(!res.has_gateway);
}
}