Feature/add blockstamp (#756)

* Add RawDelegationData

* Fix current tests for the new stored data

* Added migration commit. Will be reverted after doing the migration

* New tests for block height

* Use current blockstamp instead of 24h old one

* Put _alot_ of migration stuff in the migrate function scope
This commit is contained in:
Bogdan-Ștefan Neacşu
2021-08-31 14:51:15 +03:00
committed by GitHub
parent 122f5d9f2e
commit 92e13a5d00
7 changed files with 514 additions and 119 deletions
+16 -1
View File
@@ -2,11 +2,26 @@
#![allow(clippy::field_reassign_with_default)]
use crate::{Addr, IdentityKey};
use cosmwasm_std::Coin;
use cosmwasm_std::{Coin, Uint128};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::Display;
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct RawDelegationData {
pub amount: Uint128,
pub block_height: u64,
}
impl RawDelegationData {
pub fn new(amount: Uint128, block_height: u64) -> Self {
RawDelegationData {
amount,
block_height,
}
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct Delegation {
owner: Addr,
+1 -1
View File
@@ -10,7 +10,7 @@ mod types;
pub use cosmwasm_std::{Addr, Coin};
pub use delegation::{
Delegation, PagedGatewayDelegationsResponse, PagedMixDelegationsResponse,
PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse,
PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, RawDelegationData,
};
pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse};
pub use mixnode::{Layer, MixNode, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse};
+128 -17
View File
@@ -2,18 +2,19 @@
// SPDX-License-Identifier: Apache-2.0
use crate::helpers::calculate_epoch_reward_rate;
use crate::queries::DELEGATION_PAGE_MAX_LIMIT;
use crate::state::State;
use crate::storage::{
config, layer_distribution, reverse_gateway_delegations, reverse_mix_delegations,
};
use crate::storage::{config, gateway_delegations, layer_distribution, mix_delegations};
use crate::{error::ContractError, queries, transactions};
use config::defaults::NETWORK_MONITOR_ADDRESS;
use config::defaults::{DENOM, NETWORK_MONITOR_ADDRESS};
use cosmwasm_std::{
entry_point, to_binary, Addr, Decimal, Deps, DepsMut, Env, MessageInfo, QueryResponse,
Response, Uint128,
coin, entry_point, to_binary, Addr, Decimal, Deps, DepsMut, Env, MessageInfo, Order,
QueryResponse, Response, StdResult, Storage, Uint128,
};
use cosmwasm_storage::ReadonlyBucket;
use mixnet_contract::{
Delegation, ExecuteMsg, IdentityKey, IdentityKeyRef, InstantiateMsg, MigrateMsg, QueryMsg,
Delegation, ExecuteMsg, IdentityKey, IdentityKeyRef, InstantiateMsg, MigrateMsg,
PagedGatewayDelegationsResponse, PagedMixDelegationsResponse, QueryMsg, RawDelegationData,
StateParams,
};
@@ -94,7 +95,7 @@ pub fn instantiate(
#[entry_point]
pub fn execute(
deps: DepsMut,
_env: Env,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
@@ -113,13 +114,13 @@ pub fn execute(
transactions::try_reward_gateway(deps, info, identity, uptime)
}
ExecuteMsg::DelegateToMixnode { mix_identity } => {
transactions::try_delegate_to_mixnode(deps, info, mix_identity)
transactions::try_delegate_to_mixnode(deps, env, info, mix_identity)
}
ExecuteMsg::UndelegateFromMixnode { mix_identity } => {
transactions::try_remove_delegation_from_mixnode(deps, info, mix_identity)
}
ExecuteMsg::DelegateToGateway { gateway_identity } => {
transactions::try_delegate_to_gateway(deps, info, gateway_identity)
transactions::try_delegate_to_gateway(deps, env, info, gateway_identity)
}
ExecuteMsg::UndelegateFromGateway { gateway_identity } => {
transactions::try_remove_delegation_from_gateway(deps, info, gateway_identity)
@@ -206,7 +207,110 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
}
#[entry_point]
pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
pub fn migrate(deps: DepsMut, env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
const PREFIX_MIX_DELEGATION: &[u8] = b"md";
const PREFIX_GATEWAY_DELEGATION: &[u8] = b"gd";
const DELEGATION_PAGE_DEFAULT_LIMIT: u32 = 500;
fn calculate_start_value<S: AsRef<str>>(start_after: Option<S>) -> Option<Vec<u8>> {
start_after.as_ref().map(|identity| {
identity
.as_ref()
.as_bytes()
.iter()
.cloned()
.chain(std::iter::once(0))
.collect()
})
}
fn query_mixnode_old_delegations_paged(
deps: Deps,
mix_identity: IdentityKey,
start_after: Option<Addr>,
limit: Option<u32>,
) -> StdResult<PagedMixDelegationsResponse> {
let limit = limit
.unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT)
.min(DELEGATION_PAGE_MAX_LIMIT) as usize;
let start = calculate_start_value(start_after);
let delegations = mix_old_delegations_read(deps.storage, &mix_identity)
.range(start.as_deref(), None, Order::Ascending)
.take(limit)
.map(|res| {
res.map(|entry| {
Delegation::new(
Addr::unchecked(String::from_utf8(entry.0).expect(
"Non-UTF8 address used as key in bucket. The storage is corrupted!",
)),
coin(entry.1.u128(), DENOM),
)
})
})
.collect::<StdResult<Vec<Delegation>>>()?;
let start_next_after = delegations.last().map(|delegation| delegation.owner());
Ok(PagedMixDelegationsResponse::new(
mix_identity,
delegations,
start_next_after,
))
}
fn query_gateway_old_delegations_paged(
deps: Deps,
gateway_identity: IdentityKey,
start_after: Option<Addr>,
limit: Option<u32>,
) -> StdResult<PagedGatewayDelegationsResponse> {
let limit = limit
.unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT)
.min(DELEGATION_PAGE_MAX_LIMIT) as usize;
let start = calculate_start_value(start_after);
let delegations = gateway_old_delegations_read(deps.storage, &gateway_identity)
.range(start.as_deref(), None, Order::Ascending)
.take(limit)
.map(|res| {
res.map(|entry| {
Delegation::new(
Addr::unchecked(String::from_utf8(entry.0).expect(
"Non-UTF8 address used as key in bucket. The storage is corrupted!",
)),
coin(entry.1.u128(), DENOM),
)
})
})
.collect::<StdResult<Vec<Delegation>>>()?;
let start_next_after = delegations.last().map(|delegation| delegation.owner());
Ok(PagedGatewayDelegationsResponse::new(
gateway_identity,
delegations,
start_next_after,
))
}
fn mix_old_delegations_read<'a>(
storage: &'a dyn Storage,
mix_identity: IdentityKeyRef,
) -> ReadonlyBucket<'a, Uint128> {
ReadonlyBucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()])
}
fn gateway_old_delegations_read<'a>(
storage: &'a dyn Storage,
gateway_identity: IdentityKeyRef,
) -> ReadonlyBucket<'a, Uint128> {
ReadonlyBucket::multilevel(
storage,
&[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()],
)
}
fn get_all_mixnodes_identities(deps: &DepsMut) -> Result<Vec<IdentityKey>, ContractError> {
let mut mixnode_bonds = Vec::new();
let mut start_after = None;
@@ -258,7 +362,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, C
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = queries::query_mixnode_delegations_paged(
let mut paged_response = query_mixnode_old_delegations_paged(
deps.as_ref(),
mix_identity.into(),
start_after,
@@ -283,7 +387,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, C
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = queries::query_gateway_delegations_paged(
let mut paged_response = query_gateway_old_delegations_paged(
deps.as_ref(),
gateway_identity.into(),
start_after,
@@ -305,8 +409,11 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, C
for mix_identity in mixnodes_identities {
let delegations = get_all_mixnode_delegations(&deps, &mix_identity)?;
for delegation in delegations {
reverse_mix_delegations(deps.storage, &delegation.owner())
.save(mix_identity.as_bytes(), &())?;
let old_delegation_bucket = mix_old_delegations_read(deps.storage, &mix_identity);
let amount = old_delegation_bucket.load(delegation.owner().as_bytes())?;
let new_delegation_data = RawDelegationData::new(amount, env.block.height);
let mut delegation_bucket = mix_delegations(deps.storage, &mix_identity);
delegation_bucket.save(delegation.owner().as_bytes(), &new_delegation_data)?;
}
}
@@ -314,8 +421,12 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, C
for gateway_identity in gateways_identities {
let delegations = get_all_gateway_delegations(&deps, &gateway_identity)?;
for delegation in delegations {
reverse_gateway_delegations(deps.storage, &delegation.owner())
.save(gateway_identity.as_bytes(), &())?;
let old_delegation_bucket =
gateway_old_delegations_read(deps.storage, &gateway_identity);
let amount = old_delegation_bucket.load(delegation.owner().as_bytes())?;
let new_delegation_data = RawDelegationData::new(amount, env.block.height);
let mut delegation_bucket = gateway_delegations(deps.storage, &gateway_identity);
delegation_bucket.save(delegation.owner().as_bytes(), &new_delegation_data)?;
}
}
+24 -25
View File
@@ -128,7 +128,7 @@ pub(crate) fn query_mixnode_delegations_paged(
Addr::unchecked(String::from_utf8(entry.0).expect(
"Non-UTF8 address used as key in bucket. The storage is corrupted!",
)),
coin(entry.1.u128(), DENOM),
coin(entry.1.amount.u128(), DENOM),
)
})
})
@@ -183,7 +183,7 @@ pub(crate) fn query_mixnode_delegation(
match mix_delegations_read(deps.storage, &mix_identity).may_load(address.as_bytes())? {
Some(delegation_value) => Ok(Delegation::new(
address,
coin(delegation_value.u128(), DENOM),
coin(delegation_value.amount.u128(), DENOM),
)),
None => Err(ContractError::NoMixnodeDelegationFound {
identity: mix_identity,
@@ -212,7 +212,7 @@ pub(crate) fn query_gateway_delegations_paged(
Addr::unchecked(String::from_utf8(entry.0).expect(
"Non-UTF8 address used as key in bucket. The storage is corrupted!",
)),
coin(entry.1.u128(), DENOM),
coin(entry.1.amount.u128(), DENOM),
)
})
})
@@ -267,7 +267,7 @@ pub(crate) fn query_gateway_delegation(
match gateway_delegations_read(deps.storage, &gateway_identity).may_load(address.as_bytes())? {
Some(delegation_value) => Ok(Delegation::new(
address,
coin(delegation_value.u128(), DENOM),
coin(delegation_value.amount.u128(), DENOM),
)),
None => Err(ContractError::NoGatewayDelegationFound {
identity: gateway_identity,
@@ -282,10 +282,12 @@ mod tests {
use crate::state::State;
use crate::storage::{config, gateway_delegations, gateways, mix_delegations, mixnodes};
use crate::support::tests::helpers;
use crate::support::tests::helpers::{good_gateway_bond, good_mixnode_bond};
use crate::support::tests::helpers::{
good_gateway_bond, good_mixnode_bond, raw_delegation_fixture,
};
use crate::transactions;
use cosmwasm_std::testing::mock_info;
use cosmwasm_std::{Addr, Storage, Uint128};
use cosmwasm_std::{Addr, Storage};
use mixnet_contract::{Gateway, MixNode};
#[test]
@@ -632,14 +634,12 @@ mod tests {
#[cfg(test)]
mod querying_for_mixnode_delegations_paged {
use super::*;
use crate::storage::mix_delegations;
use cosmwasm_std::Uint128;
fn store_n_delegations(n: u32, storage: &mut dyn Storage, node_identity: &IdentityKey) {
for i in 0..n {
let address = format!("address{}", i);
mix_delegations(storage, node_identity)
.save(address.as_bytes(), &Uint128(42))
.save(address.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
}
}
@@ -711,7 +711,7 @@ mod tests {
let node_identity: IdentityKey = "foo".into();
mix_delegations(&mut deps.storage, &node_identity)
.save("1".as_bytes(), &Uint128(42))
.save("1".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
let per_page = 2;
@@ -728,7 +728,7 @@ mod tests {
// save another
mix_delegations(&mut deps.storage, &node_identity)
.save("2".as_bytes(), &Uint128(42))
.save("2".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
// page1 should have 2 results on it
@@ -742,7 +742,7 @@ mod tests {
assert_eq!(2, page1.delegations.len());
mix_delegations(&mut deps.storage, &node_identity)
.save("3".as_bytes(), &Uint128(42))
.save("3".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
// page1 still has 2 results
@@ -769,7 +769,7 @@ mod tests {
// save another one
mix_delegations(&mut deps.storage, &node_identity)
.save("4".as_bytes(), &Uint128(42))
.save("4".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
let start_after = Addr::unchecked("2");
@@ -793,7 +793,7 @@ mod tests {
let delegation_owner = Addr::unchecked("bar");
mix_delegations(&mut deps.storage, &node_identity)
.save(delegation_owner.as_bytes(), &Uint128(42))
.save(delegation_owner.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
assert_eq!(
@@ -825,7 +825,7 @@ mod tests {
// add delegation from a different address
mix_delegations(&mut deps.storage, &node_identity1)
.save(delegation_owner2.as_bytes(), &Uint128(42))
.save(delegation_owner2.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
assert_eq!(
@@ -842,7 +842,7 @@ mod tests {
// add delegation for a different node
mix_delegations(&mut deps.storage, &node_identity2)
.save(delegation_owner1.as_bytes(), &Uint128(42))
.save(delegation_owner1.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
assert_eq!(
@@ -1019,13 +1019,12 @@ mod tests {
mod querying_for_gateway_delegations_paged {
use super::*;
use crate::storage::gateway_delegations;
use cosmwasm_std::Uint128;
fn store_n_delegations(n: u32, storage: &mut dyn Storage, node_identity: &IdentityKey) {
for i in 0..n {
let address = format!("address{}", i);
gateway_delegations(storage, node_identity)
.save(address.as_bytes(), &Uint128(42))
.save(address.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
}
}
@@ -1097,7 +1096,7 @@ mod tests {
let node_identity: IdentityKey = "foo".into();
gateway_delegations(&mut deps.storage, &node_identity)
.save("1".as_bytes(), &Uint128(42))
.save("1".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
let per_page = 2;
@@ -1114,7 +1113,7 @@ mod tests {
// save another
gateway_delegations(&mut deps.storage, &node_identity)
.save("2".as_bytes(), &Uint128(42))
.save("2".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
// page1 should have 2 results on it
@@ -1128,7 +1127,7 @@ mod tests {
assert_eq!(2, page1.delegations.len());
gateway_delegations(&mut deps.storage, &node_identity)
.save("3".as_bytes(), &Uint128(42))
.save("3".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
// page1 still has 2 results
@@ -1155,7 +1154,7 @@ mod tests {
// save another one
gateway_delegations(&mut deps.storage, &node_identity)
.save("4".as_bytes(), &Uint128(42))
.save("4".as_bytes(), &raw_delegation_fixture(42))
.unwrap();
let start_after = Addr::unchecked("2");
@@ -1179,7 +1178,7 @@ mod tests {
let delegation_owner = Addr::unchecked("bar");
gateway_delegations(&mut deps.storage, &node_identity)
.save(delegation_owner.as_bytes(), &Uint128(42))
.save(delegation_owner.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
assert_eq!(
@@ -1211,7 +1210,7 @@ mod tests {
// add delegation from a different address
gateway_delegations(&mut deps.storage, &node_identity1)
.save(delegation_owner2.as_bytes(), &Uint128(42))
.save(delegation_owner2.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
assert_eq!(
@@ -1228,7 +1227,7 @@ mod tests {
// add delegation for a different node
gateway_delegations(&mut deps.storage, &node_identity2)
.save(delegation_owner1.as_bytes(), &Uint128(42))
.save(delegation_owner1.as_bytes(), &raw_delegation_fixture(42))
.unwrap();
assert_eq!(
+34 -25
View File
@@ -10,7 +10,7 @@ use cosmwasm_storage::{
};
use mixnet_contract::{
Addr, GatewayBond, IdentityKey, IdentityKeyRef, Layer, LayerDistribution, MixNodeBond,
StateParams,
RawDelegationData, StateParams,
};
// storage prefixes
@@ -193,11 +193,11 @@ pub(crate) fn increase_mix_delegated_stakes(
);
// and for each of them increase the stake proportionally to the reward
for (delegator_address, amount) in delegations_chunk.into_iter() {
let reward = amount * scaled_reward_rate;
let new_amount = amount + reward;
for (delegator_address, mut delegation) in delegations_chunk.into_iter() {
let reward = delegation.amount * scaled_reward_rate;
delegation.amount += reward;
total_rewarded += reward;
mix_delegations(storage, mix_identity).save(&delegator_address, &new_amount)?;
mix_delegations(storage, mix_identity).save(&delegator_address, &delegation)?;
}
}
@@ -237,11 +237,11 @@ pub(crate) fn increase_gateway_delegated_stakes(
);
// and for each of them increase the stake proportionally to the reward
for (delegator_address, amount) in delegations_chunk.into_iter() {
let reward = amount * scaled_reward_rate;
let new_amount = amount + reward;
for (delegator_address, mut delegation) in delegations_chunk.into_iter() {
let reward = delegation.amount * scaled_reward_rate;
delegation.amount += reward;
total_rewarded += reward;
gateway_delegations(storage, gateway_identity).save(&delegator_address, &new_amount)?;
gateway_delegations(storage, gateway_identity).save(&delegator_address, &delegation)?;
}
}
@@ -293,14 +293,14 @@ pub fn gateways_owners_read(storage: &dyn Storage) -> ReadonlyBucket<IdentityKey
pub fn mix_delegations<'a>(
storage: &'a mut dyn Storage,
mix_identity: IdentityKeyRef,
) -> Bucket<'a, Uint128> {
) -> Bucket<'a, RawDelegationData> {
Bucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()])
}
pub fn mix_delegations_read<'a>(
storage: &'a dyn Storage,
mix_identity: IdentityKeyRef,
) -> ReadonlyBucket<'a, Uint128> {
) -> ReadonlyBucket<'a, RawDelegationData> {
ReadonlyBucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()])
}
@@ -318,7 +318,7 @@ pub fn reverse_mix_delegations_read<'a>(
pub fn gateway_delegations<'a>(
storage: &'a mut dyn Storage,
gateway_identity: IdentityKeyRef,
) -> Bucket<'a, Uint128> {
) -> Bucket<'a, RawDelegationData> {
Bucket::multilevel(
storage,
&[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()],
@@ -328,7 +328,7 @@ pub fn gateway_delegations<'a>(
pub fn gateway_delegations_read<'a>(
storage: &'a dyn Storage,
gateway_identity: IdentityKeyRef,
) -> ReadonlyBucket<'a, Uint128> {
) -> ReadonlyBucket<'a, RawDelegationData> {
ReadonlyBucket::multilevel(
storage,
&[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()],
@@ -382,6 +382,7 @@ mod tests {
use super::*;
use crate::support::tests::helpers::{
gateway_bond_fixture, gateway_fixture, mix_node_fixture, mixnode_bond_fixture,
raw_delegation_fixture,
};
use config::defaults::DENOM;
use cosmwasm_std::testing::MockStorage;
@@ -523,7 +524,10 @@ mod tests {
let delegator_address = Addr::unchecked("bob");
mix_delegations(&mut deps.storage, &node_identity)
.save(delegator_address.as_bytes(), &Uint128(1000))
.save(
delegator_address.as_bytes(),
&RawDelegationData::new(1000u128.into(), 42),
)
.unwrap();
let total_increase =
@@ -532,8 +536,9 @@ mod tests {
assert_eq!(Uint128(1), total_increase);
// amount is incremented, block height remains the same
assert_eq!(
Uint128(1001),
RawDelegationData::new(1001u128.into(), 42),
mix_delegations_read(&mut deps.storage, &node_identity)
.load(delegator_address.as_bytes())
.unwrap()
@@ -551,7 +556,7 @@ mod tests {
for i in 0..100 {
let delegator_address = Addr::unchecked(format!("address{}", i));
mix_delegations(&mut deps.storage, &node_identity)
.save(delegator_address.as_bytes(), &Uint128(1000))
.save(delegator_address.as_bytes(), &raw_delegation_fixture(1000))
.unwrap();
}
@@ -564,7 +569,7 @@ mod tests {
for i in 0..100 {
let delegator_address = Addr::unchecked(format!("address{}", i));
assert_eq!(
Uint128(1001),
raw_delegation_fixture(1001),
mix_delegations_read(&mut deps.storage, &node_identity)
.load(delegator_address.as_bytes())
.unwrap()
@@ -583,7 +588,7 @@ mod tests {
for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 {
let delegator_address = Addr::unchecked(format!("address{}", i));
mix_delegations(&mut deps.storage, &node_identity)
.save(delegator_address.as_bytes(), &Uint128(1000))
.save(delegator_address.as_bytes(), &raw_delegation_fixture(1000))
.unwrap();
}
@@ -599,7 +604,7 @@ mod tests {
for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 {
let delegator_address = Addr::unchecked(format!("address{}", i));
assert_eq!(
Uint128(1001),
raw_delegation_fixture(1001),
mix_delegations_read(&mut deps.storage, &node_identity)
.load(delegator_address.as_bytes())
.unwrap()
@@ -716,7 +721,10 @@ mod tests {
let delegator_address = Addr::unchecked("bob");
gateway_delegations(&mut deps.storage, &node_identity)
.save(delegator_address.as_bytes(), &Uint128(1000))
.save(
delegator_address.as_bytes(),
&RawDelegationData::new(1000u128.into(), 42),
)
.unwrap();
let total_increase = increase_gateway_delegated_stakes(
@@ -728,8 +736,9 @@ mod tests {
assert_eq!(Uint128(1), total_increase);
// amount is incremented, block height remains the same
assert_eq!(
Uint128(1001),
RawDelegationData::new(1001u128.into(), 42),
gateway_delegations_read(&mut deps.storage, &node_identity)
.load(delegator_address.as_bytes())
.unwrap()
@@ -747,7 +756,7 @@ mod tests {
for i in 0..100 {
let delegator_address = Addr::unchecked(format!("address{}", i));
gateway_delegations(&mut deps.storage, &node_identity)
.save(delegator_address.as_bytes(), &Uint128(1000))
.save(delegator_address.as_bytes(), &raw_delegation_fixture(1000))
.unwrap();
}
@@ -763,7 +772,7 @@ mod tests {
for i in 0..100 {
let delegator_address = Addr::unchecked(format!("address{}", i));
assert_eq!(
Uint128(1001),
raw_delegation_fixture(1001),
gateway_delegations_read(&mut deps.storage, &node_identity)
.load(delegator_address.as_bytes())
.unwrap()
@@ -782,7 +791,7 @@ mod tests {
for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 {
let delegator_address = Addr::unchecked(format!("address{}", i));
gateway_delegations(&mut deps.storage, &node_identity)
.save(delegator_address.as_bytes(), &Uint128(1000))
.save(delegator_address.as_bytes(), &raw_delegation_fixture(1000))
.unwrap();
}
@@ -801,7 +810,7 @@ mod tests {
for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 {
let delegator_address = Addr::unchecked(format!("address{}", i));
assert_eq!(
Uint128(1001),
raw_delegation_fixture(1001),
gateway_delegations_read(&mut deps.storage, &node_identity)
.load(delegator_address.as_bytes())
.unwrap()
+6 -2
View File
@@ -5,7 +5,6 @@ pub mod helpers {
use crate::contract::{instantiate, INITIAL_MIXNODE_BOND};
use crate::transactions::{try_add_gateway, try_add_mixnode};
use config::defaults::DENOM;
use cosmwasm_std::coin;
use cosmwasm_std::from_binary;
use cosmwasm_std::testing::mock_dependencies;
use cosmwasm_std::testing::mock_env;
@@ -16,10 +15,11 @@ pub mod helpers {
use cosmwasm_std::Addr;
use cosmwasm_std::Coin;
use cosmwasm_std::OwnedDeps;
use cosmwasm_std::{coin, Uint128};
use cosmwasm_std::{Empty, MemoryStorage};
use mixnet_contract::{
Gateway, GatewayBond, InstantiateMsg, Layer, MixNode, MixNodeBond, PagedGatewayResponse,
PagedMixnodeResponse, QueryMsg,
PagedMixnodeResponse, QueryMsg, RawDelegationData,
};
pub fn add_mixnode(
@@ -159,6 +159,10 @@ pub mod helpers {
GatewayBond::new(coin(50, DENOM), Addr::unchecked("foo"), gateway)
}
pub fn raw_delegation_fixture(amount: u128) -> RawDelegationData {
RawDelegationData::new(Uint128(amount), 42)
}
pub fn query_contract_balance(
address: Addr,
deps: OwnedDeps<MockStorage, MockApi, MockQuerier>,
+305 -48
View File
@@ -7,11 +7,12 @@ use crate::queries;
use crate::storage::*;
use config::defaults::DENOM;
use cosmwasm_std::{
attr, coins, BankMsg, Coin, Decimal, DepsMut, MessageInfo, Order, Response, StdResult, Uint128,
attr, coins, BankMsg, Coin, Decimal, DepsMut, Env, MessageInfo, Order, Response, StdResult,
Uint128,
};
use cosmwasm_storage::ReadonlyBucket;
use mixnet_contract::{
Gateway, GatewayBond, IdentityKey, Layer, MixNode, MixNodeBond, StateParams,
Gateway, GatewayBond, IdentityKey, Layer, MixNode, MixNodeBond, RawDelegationData, StateParams,
};
const OLD_DELEGATIONS_CHUNK_SIZE: usize = 500;
@@ -23,7 +24,7 @@ const OLD_DELEGATIONS_CHUNK_SIZE: usize = 500;
// 3. The node unbonds
// 4. Some of the addresses that delegated in the past have not removed the delegation yet
// 5. The node rebonds with the same identity
fn find_old_delegations(delegations_bucket: ReadonlyBucket<Uint128>) -> StdResult<Coin> {
fn find_old_delegations(delegations_bucket: ReadonlyBucket<RawDelegationData>) -> StdResult<Coin> {
// I think it's incredibly unlikely to ever read more than that
// but in case we do, we should guard ourselves against possible
// out of memory errors (wasm contracts can only allocate at most 2MB
@@ -45,7 +46,7 @@ fn find_old_delegations(delegations_bucket: ReadonlyBucket<Uint128>) -> StdResul
continue;
}
let value = delegation?.1;
let value = delegation?.1.amount;
total_delegation.amount += value;
}
@@ -540,6 +541,7 @@ fn validate_delegation_stake(delegation: &[Coin]) -> Result<(), ContractError> {
pub(crate) fn try_delegate_to_mixnode(
deps: DepsMut,
env: Env,
info: MessageInfo,
mix_identity: IdentityKey,
) -> Result<Response, ContractError> {
@@ -565,12 +567,13 @@ pub(crate) fn try_delegate_to_mixnode(
let sender_bytes = info.sender.as_bytes();
// write the delegation
match delegation_bucket.may_load(sender_bytes)? {
Some(existing_delegation) => {
delegation_bucket.save(sender_bytes, &(existing_delegation + info.funds[0].amount))?
}
None => delegation_bucket.save(sender_bytes, &info.funds[0].amount)?,
}
let new_amount = match delegation_bucket.may_load(sender_bytes)? {
Some(existing_delegation) => existing_delegation.amount + info.funds[0].amount,
None => info.funds[0].amount,
};
// the block height is reset, if it existed
let new_delegation = RawDelegationData::new(new_amount, env.block.height);
delegation_bucket.save(sender_bytes, &new_delegation)?;
reverse_mix_delegations(deps.storage, &info.sender).save(mix_identity.as_bytes(), &())?;
@@ -593,7 +596,7 @@ pub(crate) fn try_remove_delegation_from_mixnode(
// send delegated funds back to the delegation owner
let messages = vec![BankMsg::Send {
to_address: info.sender.to_string(),
amount: coins(delegation.u128(), DENOM),
amount: coins(delegation.amount.u128(), DENOM),
}
.into()];
@@ -606,7 +609,7 @@ pub(crate) fn try_remove_delegation_from_mixnode(
existing_bond.total_delegation.amount = existing_bond
.total_delegation
.amount
.checked_sub(delegation)
.checked_sub(delegation.amount)
.unwrap();
mixnodes_bucket.save(mix_identity.as_bytes(), &existing_bond)?;
}
@@ -627,6 +630,7 @@ pub(crate) fn try_remove_delegation_from_mixnode(
pub(crate) fn try_delegate_to_gateway(
deps: DepsMut,
env: Env,
info: MessageInfo,
gateway_identity: IdentityKey,
) -> Result<Response, ContractError> {
@@ -652,12 +656,13 @@ pub(crate) fn try_delegate_to_gateway(
let sender_bytes = info.sender.as_bytes();
// write the delegation
match delegation_bucket.may_load(sender_bytes)? {
Some(existing_delegation) => {
delegation_bucket.save(sender_bytes, &(existing_delegation + info.funds[0].amount))?
}
None => delegation_bucket.save(sender_bytes, &info.funds[0].amount)?,
}
let new_amount = match delegation_bucket.may_load(sender_bytes)? {
Some(existing_delegation) => existing_delegation.amount + info.funds[0].amount,
None => info.funds[0].amount,
};
// the block height is reset, if it existed
let new_delegation = RawDelegationData::new(new_amount, env.block.height);
delegation_bucket.save(sender_bytes, &new_delegation)?;
reverse_gateway_delegations(deps.storage, &info.sender)
.save(gateway_identity.as_bytes(), &())?;
@@ -682,7 +687,7 @@ pub(crate) fn try_remove_delegation_from_gateway(
// send delegated funds back to the delegation owner
let messages = vec![BankMsg::Send {
to_address: info.sender.to_string(),
amount: coins(delegation.u128(), DENOM),
amount: coins(delegation.amount.u128(), DENOM),
}
.into()];
@@ -697,7 +702,7 @@ pub(crate) fn try_remove_delegation_from_gateway(
existing_bond.total_delegation.amount = existing_bond
.total_delegation
.amount
.checked_sub(delegation)
.checked_sub(delegation.amount)
.unwrap();
gateways_bucket.save(gateway_identity.as_bytes(), &existing_bond)?;
}
@@ -734,7 +739,7 @@ pub mod tests {
use crate::support::tests::helpers;
use crate::support::tests::helpers::{
add_gateway, add_mixnode, gateway_fixture, good_gateway_bond, good_mixnode_bond,
mix_node_fixture,
mix_node_fixture, raw_delegation_fixture,
};
use cosmwasm_std::testing::{mock_env, mock_info};
use cosmwasm_std::{coin, coins, from_binary, Addr, Uint128};
@@ -1802,7 +1807,7 @@ pub mod tests {
.unwrap();
mix_delegations(&mut deps.storage, &node_identity)
.save(b"delegator", &Uint128(initial_delegation))
.save(b"delegator", &raw_delegation_fixture(initial_delegation))
.unwrap();
let bond_reward_rate = read_mixnode_epoch_bond_reward_rate(deps.as_ref().storage);
@@ -1901,7 +1906,7 @@ pub mod tests {
.unwrap();
gateway_delegations(&mut deps.storage, &node_identity)
.save(b"delegator", &Uint128(initial_delegation))
.save(b"delegator", &raw_delegation_fixture(initial_delegation))
.unwrap();
let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage);
@@ -2027,6 +2032,7 @@ pub mod tests {
}),
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info("sender", &coins(123, DENOM)),
"non-existent-mix-identity".into()
)
@@ -2043,13 +2049,14 @@ pub mod tests {
let delegation = coin(123, DENOM);
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone()
)
.is_ok());
assert_eq!(
delegation.amount,
RawDelegationData::new(delegation.amount, mock_env().block.height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
@@ -2086,6 +2093,7 @@ pub mod tests {
}),
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(123, DENOM)),
identity
)
@@ -2105,13 +2113,14 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone()
)
.is_ok());
assert_eq!(
delegation.amount,
RawDelegationData::new(delegation.amount, mock_env().block.height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
@@ -2144,6 +2153,7 @@ pub mod tests {
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation1.clone()]),
identity.clone(),
)
@@ -2151,13 +2161,17 @@ pub mod tests {
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation2.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
delegation1.amount + delegation2.amount,
RawDelegationData::new(
delegation1.amount + delegation2.amount,
mock_env().block.height
),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
@@ -2179,6 +2193,106 @@ pub mod tests {
)
}
#[test]
fn block_height_is_updated_on_new_delegation() {
let mut deps = helpers::init_contract();
let mixnode_owner = "bob";
let identity = add_mixnode(mixnode_owner, good_mixnode_bond(), &mut deps);
let delegation_owner = Addr::unchecked("sender");
let delegation = coin(100, DENOM);
let env1 = mock_env();
let mut env2 = mock_env();
let initial_height = env1.block.height;
let updated_height = initial_height + 42;
// second env has grown in block height
env2.block.height = updated_height;
try_delegate_to_mixnode(
deps.as_mut(),
env1,
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation.amount, initial_height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
);
try_delegate_to_mixnode(
deps.as_mut(),
env2,
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation.amount + delegation.amount, updated_height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
);
}
#[test]
fn block_height_is_not_updated_on_different_delegator() {
let mut deps = helpers::init_contract();
let mixnode_owner = "bob";
let identity = add_mixnode(mixnode_owner, good_mixnode_bond(), &mut deps);
let delegation_owner1 = Addr::unchecked("sender1");
let delegation_owner2 = Addr::unchecked("sender2");
let delegation1 = coin(100, DENOM);
let delegation2 = coin(120, DENOM);
let env1 = mock_env();
let mut env2 = mock_env();
let initial_height = env1.block.height;
let second_height = initial_height + 42;
// second env has grown in block height
env2.block.height = second_height;
try_delegate_to_mixnode(
deps.as_mut(),
env1,
mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation1.amount, initial_height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner1.as_bytes())
.unwrap()
);
try_delegate_to_mixnode(
deps.as_mut(),
env2,
mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation1.amount, initial_height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner1.as_bytes())
.unwrap()
);
assert_eq!(
RawDelegationData::new(delegation2.amount, second_height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner2.as_bytes())
.unwrap()
);
}
#[test]
fn is_disallowed_for_already_delegated_node_if_it_unbonded() {
let mut deps = helpers::init_contract();
@@ -2189,6 +2303,7 @@ pub mod tests {
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -2202,6 +2317,7 @@ pub mod tests {
}),
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(50, DENOM)),
identity
)
@@ -2219,6 +2335,7 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(123, DENOM)),
identity1.clone()
)
@@ -2226,17 +2343,17 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(42, DENOM)),
identity2.clone()
)
.is_ok());
assert_eq!(
123,
RawDelegationData::new(123u128.into(), mock_env().block.height),
mix_delegations_read(&deps.storage, &identity1)
.load(delegation_owner.as_bytes())
.unwrap()
.u128()
);
assert!(
reverse_mix_delegations_read(&deps.storage, &delegation_owner)
@@ -2245,11 +2362,10 @@ pub mod tests {
);
assert_eq!(
42,
RawDelegationData::new(42u128.into(), mock_env().block.height),
mix_delegations_read(&deps.storage, &identity2)
.load(delegation_owner.as_bytes())
.unwrap()
.u128()
);
assert!(
reverse_mix_delegations_read(&deps.storage, &delegation_owner)
@@ -2269,6 +2385,7 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info("sender1", &vec![delegation1.clone()]),
identity.clone()
)
@@ -2276,6 +2393,7 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info("sender2", &vec![delegation2.clone()]),
identity.clone()
)
@@ -2302,6 +2420,7 @@ pub mod tests {
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -2310,11 +2429,10 @@ pub mod tests {
try_remove_mixnode(deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
assert_eq!(
100,
RawDelegationData::new(100u128.into(), mock_env().block.height),
mix_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
.u128()
);
assert!(
reverse_mix_delegations_read(&deps.storage, &delegation_owner)
@@ -2361,6 +2479,7 @@ pub mod tests {
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -2416,6 +2535,7 @@ pub mod tests {
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -2466,6 +2586,7 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]),
identity.clone()
)
@@ -2473,6 +2594,7 @@ pub mod tests {
assert!(try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]),
identity.clone()
)
@@ -2513,13 +2635,13 @@ pub mod tests {
let identity = add_mixnode(node_owner, good_mixnode_bond(), &mut deps);
mix_delegations(&mut deps.storage, &identity)
.save(b"delegator1", &Uint128(initial_delegation1))
.save(b"delegator1", &raw_delegation_fixture(initial_delegation1))
.unwrap();
mix_delegations(&mut deps.storage, &identity)
.save(b"delegator2", &Uint128(initial_delegation2))
.save(b"delegator2", &raw_delegation_fixture(initial_delegation2))
.unwrap();
mix_delegations(&mut deps.storage, &identity)
.save(b"delegator3", &Uint128(initial_delegation3))
.save(b"delegator3", &raw_delegation_fixture(initial_delegation3))
.unwrap();
let bond_reward = read_mixnode_epoch_bond_reward_rate(deps.as_ref().storage);
@@ -2550,6 +2672,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator1".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2557,6 +2680,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator2".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2564,6 +2688,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator3".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2606,6 +2731,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator1".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2613,6 +2739,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator2".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2620,6 +2747,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator3".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2649,6 +2777,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator1".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2656,6 +2785,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator2".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2663,6 +2793,7 @@ pub mod tests {
mix_delegations_read(deps.as_ref().storage, &identity)
.load("delegator3".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -2689,6 +2820,7 @@ pub mod tests {
}),
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info("sender", &coins(123, DENOM)),
"non-existent-gateway-identity".into()
)
@@ -2705,13 +2837,14 @@ pub mod tests {
let delegation = coin(123, DENOM);
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone()
)
.is_ok());
assert_eq!(
delegation.amount,
RawDelegationData::new(delegation.amount, mock_env().block.height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
@@ -2748,6 +2881,7 @@ pub mod tests {
}),
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(123, DENOM)),
identity
)
@@ -2767,13 +2901,14 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone()
)
.is_ok());
assert_eq!(
delegation.amount,
RawDelegationData::new(delegation.amount, mock_env().block.height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
@@ -2806,6 +2941,7 @@ pub mod tests {
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation1.clone()]),
identity.clone(),
)
@@ -2813,13 +2949,17 @@ pub mod tests {
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &vec![delegation2.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
delegation1.amount + delegation2.amount,
RawDelegationData::new(
delegation1.amount + delegation2.amount,
mock_env().block.height
),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
@@ -2841,6 +2981,106 @@ pub mod tests {
)
}
#[test]
fn block_height_is_updated_on_new_delegation() {
let mut deps = helpers::init_contract();
let gateway_owner = "bob";
let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps);
let delegation_owner = Addr::unchecked("sender");
let delegation = coin(100, DENOM);
let env1 = mock_env();
let mut env2 = mock_env();
let initial_height = env1.block.height;
let updated_height = initial_height + 42;
// second env has grown in block height
env2.block.height = updated_height;
try_delegate_to_gateway(
deps.as_mut(),
env1,
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation.amount, initial_height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
);
try_delegate_to_gateway(
deps.as_mut(),
env2,
mock_info(delegation_owner.as_str(), &vec![delegation.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation.amount + delegation.amount, updated_height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
);
}
#[test]
fn block_height_is_not_updated_on_different_delegator() {
let mut deps = helpers::init_contract();
let gateway_owner = "bob";
let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps);
let delegation_owner1 = Addr::unchecked("sender1");
let delegation_owner2 = Addr::unchecked("sender2");
let delegation1 = coin(100, DENOM);
let delegation2 = coin(120, DENOM);
let env1 = mock_env();
let mut env2 = mock_env();
let initial_height = env1.block.height;
let second_height = initial_height + 42;
// second env has grown in block height
env2.block.height = second_height;
try_delegate_to_gateway(
deps.as_mut(),
env1,
mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation1.amount, initial_height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner1.as_bytes())
.unwrap()
);
try_delegate_to_gateway(
deps.as_mut(),
env2,
mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]),
identity.clone(),
)
.unwrap();
assert_eq!(
RawDelegationData::new(delegation1.amount, initial_height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner1.as_bytes())
.unwrap()
);
assert_eq!(
RawDelegationData::new(delegation2.amount, second_height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner2.as_bytes())
.unwrap()
);
}
#[test]
fn is_disallowed_for_already_delegated_node_if_it_unbonded() {
let mut deps = helpers::init_contract();
@@ -2851,6 +3091,7 @@ pub mod tests {
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -2864,6 +3105,7 @@ pub mod tests {
}),
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(50, DENOM)),
identity.clone()
)
@@ -2881,6 +3123,7 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(123, DENOM)),
identity1.clone()
)
@@ -2888,17 +3131,17 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(42, DENOM)),
identity2.clone()
)
.is_ok());
assert_eq!(
123,
RawDelegationData::new(123u128.into(), mock_env().block.height),
gateway_delegations_read(&deps.storage, &identity1)
.load(delegation_owner.as_bytes())
.unwrap()
.u128()
);
assert!(
reverse_gateway_delegations_read(&deps.storage, &delegation_owner)
@@ -2907,11 +3150,10 @@ pub mod tests {
);
assert_eq!(
42,
RawDelegationData::new(42u128.into(), mock_env().block.height),
gateway_delegations_read(&deps.storage, &identity2)
.load(delegation_owner.as_bytes())
.unwrap()
.u128()
);
assert!(
reverse_gateway_delegations_read(&deps.storage, &delegation_owner)
@@ -2931,6 +3173,7 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info("sender1", &vec![delegation1.clone()]),
identity.clone()
)
@@ -2938,6 +3181,7 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info("sender2", &vec![delegation2.clone()]),
identity.clone()
)
@@ -2964,6 +3208,7 @@ pub mod tests {
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -2972,11 +3217,10 @@ pub mod tests {
try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap();
assert_eq!(
100,
RawDelegationData::new(100u128.into(), mock_env().block.height),
gateway_delegations_read(&deps.storage, &identity)
.load(delegation_owner.as_bytes())
.unwrap()
.u128()
);
assert!(
reverse_gateway_delegations_read(&deps.storage, &delegation_owner)
@@ -3023,6 +3267,7 @@ pub mod tests {
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -3078,6 +3323,7 @@ pub mod tests {
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
@@ -3128,6 +3374,7 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]),
identity.clone()
)
@@ -3135,6 +3382,7 @@ pub mod tests {
assert!(try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]),
identity.clone()
)
@@ -3175,13 +3423,13 @@ pub mod tests {
let identity = add_gateway(node_owner, good_gateway_bond(), &mut deps);
gateway_delegations(&mut deps.storage, &identity)
.save(b"delegator1", &Uint128(initial_delegation1))
.save(b"delegator1", &raw_delegation_fixture(initial_delegation1))
.unwrap();
gateway_delegations(&mut deps.storage, &identity)
.save(b"delegator2", &Uint128(initial_delegation2))
.save(b"delegator2", &raw_delegation_fixture(initial_delegation2))
.unwrap();
gateway_delegations(&mut deps.storage, &identity)
.save(b"delegator3", &Uint128(initial_delegation3))
.save(b"delegator3", &raw_delegation_fixture(initial_delegation3))
.unwrap();
let bond_reward = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage);
@@ -3212,6 +3460,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator1".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3219,6 +3468,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator2".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3226,6 +3476,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator3".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3268,6 +3519,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator1".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3275,6 +3527,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator2".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3282,6 +3535,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator3".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3311,6 +3565,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator1".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3318,6 +3573,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator2".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3325,6 +3581,7 @@ pub mod tests {
gateway_delegations_read(deps.as_ref().storage, &identity)
.load("delegator3".as_bytes())
.unwrap()
.amount
);
assert_eq!(
@@ -3373,7 +3630,7 @@ pub mod tests {
let mut write_bucket = mix_delegations(&mut deps.storage, &node_identity);
for i in 1..=total_delegations {
let delegator = Addr::unchecked(format!("delegator{}", i));
let delegation = Uint128(i as u128);
let delegation = raw_delegation_fixture(i as u128);
write_bucket
.save(delegator.as_bytes(), &delegation)
.unwrap();