Skip to content

Commit

Permalink
Merge branch 'tiago/eth-voting-power' (#1865)
Browse files Browse the repository at this point in the history
  • Loading branch information
sug0 committed Sep 21, 2023
2 parents a2213d8 + 8049d74 commit fdcea56
Show file tree
Hide file tree
Showing 15 changed files with 439 additions and 401 deletions.
2 changes: 2 additions & 0 deletions .changelog/unreleased/improvements/1865-eth-voting-power.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Rework voting on Ethereum tallies across epoch boundaries
([\#1865](https://github.com/anoma/namada/pull/1865))
6 changes: 5 additions & 1 deletion core/src/types/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,13 @@ impl Amount {
denom: impl Into<u8>,
) -> Result<Self, AmountParseError> {
let denom = denom.into();
let uint = uint.into();
if denom == 0 {
return Ok(Self { raw: uint });
}
match Uint::from(10)
.checked_pow(Uint::from(denom))
.and_then(|scaling| scaling.checked_mul(uint.into()))
.and_then(|scaling| scaling.checked_mul(uint))
{
Some(amount) => Ok(Self { raw: amount }),
None => Err(AmountParseError::ConvertToDecimal),
Expand Down
19 changes: 19 additions & 0 deletions core/src/types/voting_power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use num_traits::ops::checked::CheckedAdd;
use serde::de::Visitor;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use crate::types::token::Amount;
use crate::types::uint::Uint;

/// Namada voting power, normalized to the range `0 - 2^32`.
Expand Down Expand Up @@ -170,6 +171,24 @@ impl Mul<&FractionalVotingPower> for FractionalVotingPower {
}
}

impl Mul<Amount> for FractionalVotingPower {
type Output = Amount;

fn mul(self, rhs: Amount) -> Self::Output {
self * &rhs
}
}

impl Mul<&Amount> for FractionalVotingPower {
type Output = Amount;

fn mul(self, &rhs: &Amount) -> Self::Output {
let whole: Uint = rhs.into();
let fraction = (self.0 * whole).to_integer();
Amount::from_uint(fraction, 0u8).unwrap()
}
}

impl Add<FractionalVotingPower> for FractionalVotingPower {
type Output = Self;

Expand Down
60 changes: 26 additions & 34 deletions ethereum_bridge/src/protocol/transactions/bridge_pool_roots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use namada_core::ledger::storage::{DBIter, StorageHasher, WlStorage, DB};
use namada_core::ledger::storage_api::StorageWrite;
use namada_core::types::address::Address;
use namada_core::types::storage::BlockHeight;
use namada_core::types::token::Amount;
use namada_core::types::transaction::TxResult;
use namada_core::types::vote_extensions::bridge_pool_roots::MultiSignedVext;
use namada_core::types::voting_power::FractionalVotingPower;
use namada_proof_of_stake::pos_queries::PosQueries;

use crate::protocol::transactions::utils::GetVoters;
Expand Down Expand Up @@ -140,7 +140,7 @@ fn apply_update<D, H>(
wl_storage: &mut WlStorage<D, H>,
mut update: BridgePoolRoot,
seen_by: Votes,
voting_powers: &HashMap<(Address, BlockHeight), FractionalVotingPower>,
voting_powers: &HashMap<(Address, BlockHeight), Amount>,
) -> Result<(ChangedKeys, bool)>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
Expand Down Expand Up @@ -196,17 +196,13 @@ mod test_apply_bp_roots_to_storage {
use namada_core::ledger::storage_api::StorageRead;
use namada_core::proto::{SignableEthMessage, Signed};
use namada_core::types::address;
use namada_core::types::dec::Dec;
use namada_core::types::ethereum_events::Uint;
use namada_core::types::keccak::{keccak_hash, KeccakHash};
use namada_core::types::key::RefTo;
use namada_core::types::storage::Key;
use namada_core::types::token::Amount;
use namada_core::types::vote_extensions::bridge_pool_roots;
use namada_core::types::voting_power::FractionalVotingPower;
use namada_proof_of_stake::parameters::PosParams;
use namada_proof_of_stake::{
become_validator, bond_tokens, write_pos_params, BecomeValidator,
};
use namada_proof_of_stake::write_pos_params;

use super::*;
use crate::protocol::transactions::votes::{
Expand Down Expand Up @@ -435,7 +431,7 @@ mod test_apply_bp_roots_to_storage {
.read::<EpochedVotingPower>(&bp_root_key.voting_power())
.expect("Test failed")
.expect("Test failed")
.average_voting_power(&wl_storage);
.fractional_stake(&wl_storage);
assert_eq!(
voting_power,
FractionalVotingPower::new_u64(5, 12).unwrap()
Expand All @@ -454,7 +450,7 @@ mod test_apply_bp_roots_to_storage {
.read::<EpochedVotingPower>(&bp_root_key.voting_power())
.expect("Test failed")
.expect("Test failed")
.average_voting_power(&wl_storage);
.fractional_stake(&wl_storage);
assert_eq!(voting_power, FractionalVotingPower::new_u64(5, 6).unwrap());
}

Expand Down Expand Up @@ -720,32 +716,16 @@ mod test_apply_bp_roots_to_storage {
pipeline_len: 1,
..Default::default()
};
write_pos_params(&mut wl_storage, params.clone()).expect("Test failed");
write_pos_params(&mut wl_storage, params).expect("Test failed");

// insert validators 2 and 3 at epoch 1
for (validator, stake) in [
(&validator_2, validator_2_stake),
(&validator_3, validator_3_stake),
] {
let keys = test_utils::TestValidatorKeys::generate();
let consensus_key = &keys.consensus.ref_to();
let eth_cold_key = &keys.eth_gov.ref_to();
let eth_hot_key = &keys.eth_bridge.ref_to();
become_validator(BecomeValidator {
storage: &mut wl_storage,
params: &params,
address: validator,
consensus_key,
eth_cold_key,
eth_hot_key,
current_epoch: 0.into(),
commission_rate: Dec::new(5, 2).unwrap(),
max_commission_rate_change: Dec::new(1, 2).unwrap(),
})
.expect("Test failed");
bond_tokens(&mut wl_storage, None, validator, stake, 0.into())
.expect("Test failed");
}
test_utils::append_validators_to_storage(
&mut wl_storage,
HashMap::from([
(validator_2.clone(), validator_2_stake),
(validator_3.clone(), validator_3_stake),
]),
);

// query validators to make sure they were inserted correctly
macro_rules! query_validators {
Expand All @@ -770,6 +750,12 @@ mod test_apply_bp_roots_to_storage {
epoch_0_validators,
HashMap::from([(validator_1.clone(), validator_1_stake)])
);
assert_eq!(
wl_storage
.pos_queries()
.get_total_voting_power(Some(0.into())),
validator_1_stake,
);
assert_eq!(
epoch_1_validators,
HashMap::from([
Expand All @@ -778,6 +764,12 @@ mod test_apply_bp_roots_to_storage {
(validator_3, validator_3_stake),
])
);
assert_eq!(
wl_storage
.pos_queries()
.get_total_voting_power(Some(1.into())),
validator_1_stake + validator_2_stake + validator_3_stake,
);

// set up the bridge pool's storage
bridge_pool_vp::init_storage(&mut wl_storage);
Expand Down
28 changes: 12 additions & 16 deletions ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use namada_core::ledger::storage::{DBIter, WlStorage, DB};
use namada_core::types::address::Address;
use namada_core::types::ethereum_events::EthereumEvent;
use namada_core::types::storage::{BlockHeight, Epoch, Key};
use namada_core::types::token::Amount;
use namada_core::types::transaction::TxResult;
use namada_core::types::vote_extensions::ethereum_events::MultiSignedEthEvent;
use namada_core::types::voting_power::FractionalVotingPower;
use namada_proof_of_stake::pos_queries::PosQueries;

use super::ChangedKeys;
Expand Down Expand Up @@ -86,7 +86,7 @@ where
pub(super) fn apply_updates<D, H>(
wl_storage: &mut WlStorage<D, H>,
updates: HashSet<EthMsgUpdate>,
voting_powers: HashMap<(Address, BlockHeight), FractionalVotingPower>,
voting_powers: HashMap<(Address, BlockHeight), Amount>,
) -> Result<ChangedKeys>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
Expand Down Expand Up @@ -133,7 +133,7 @@ where
fn apply_update<D, H>(
wl_storage: &mut WlStorage<D, H>,
update: EthMsgUpdate,
voting_powers: &HashMap<(Address, BlockHeight), FractionalVotingPower>,
voting_powers: &HashMap<(Address, BlockHeight), Amount>,
) -> Result<(ChangedKeys, bool)>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
Expand Down Expand Up @@ -284,7 +284,8 @@ mod tests {
use namada_core::types::ethereum_events::{
EthereumEvent, TransferToNamada,
};
use namada_core::types::token::{balance_key, minted_balance_key, Amount};
use namada_core::types::token::{balance_key, minted_balance_key};
use namada_core::types::voting_power::FractionalVotingPower;

use super::*;
use crate::protocol::transactions::utils::GetVoters;
Expand All @@ -305,7 +306,7 @@ mod tests {
#[test]
/// Test applying a `TransfersToNamada` batch containing a single transfer
fn test_apply_single_transfer() -> Result<()> {
let sole_validator = address::testing::gen_established_address();
let (sole_validator, validator_stake) = test_utils::default_validator();
let receiver = address::testing::established_address_2();

let amount = arbitrary_amount();
Expand All @@ -326,10 +327,9 @@ mod tests {
let updates = HashSet::from_iter(vec![update]);
let voting_powers = HashMap::from_iter(vec![(
(sole_validator.clone(), BlockHeight(100)),
FractionalVotingPower::WHOLE,
validator_stake,
)]);
let mut wl_storage = TestWlStorage::default();
test_utils::bootstrap_ethereum_bridge(&mut wl_storage);
let (mut wl_storage, _) = test_utils::setup_default_storage();
test_utils::whitelist_tokens(
&mut wl_storage,
[(
Expand Down Expand Up @@ -377,7 +377,7 @@ mod tests {
let voting_power = wl_storage
.read::<EpochedVotingPower>(&eth_msg_keys.voting_power())?
.expect("Test failed")
.average_voting_power(&wl_storage);
.fractional_stake(&wl_storage);
assert_eq!(voting_power, FractionalVotingPower::WHOLE);

let epoch_bytes =
Expand Down Expand Up @@ -414,7 +414,6 @@ mod tests {
test_utils::setup_storage_with_validators(HashMap::from_iter(
vec![(sole_validator.clone(), Amount::native_whole(100))],
));
test_utils::bootstrap_ethereum_bridge(&mut wl_storage);
test_utils::whitelist_tokens(
&mut wl_storage,
[(
Expand Down Expand Up @@ -488,7 +487,6 @@ mod tests {
(validator_b, Amount::native_whole(100)),
]),
);
test_utils::bootstrap_ethereum_bridge(&mut wl_storage);
let receiver = address::testing::established_address_1();

let event = EthereumEvent::TransfersToNamada {
Expand Down Expand Up @@ -590,7 +588,7 @@ mod tests {
let voting_power = wl_storage
.read::<EpochedVotingPower>(&eth_msg_keys.voting_power())?
.expect("Test failed")
.average_voting_power(&wl_storage);
.fractional_stake(&wl_storage);
assert_eq!(voting_power, FractionalVotingPower::HALF);

Ok(())
Expand Down Expand Up @@ -664,7 +662,6 @@ mod tests {
(validator_b, Amount::native_whole(100)),
]),
);
test_utils::bootstrap_ethereum_bridge(&mut wl_storage);
let receiver = address::testing::established_address_1();

let event = EthereumEvent::TransfersToNamada {
Expand Down Expand Up @@ -793,7 +790,6 @@ mod tests {
(validator_b.clone(), Amount::native_whole(100)),
]),
);
test_utils::bootstrap_ethereum_bridge(&mut wl_storage);

let receiver = address::testing::established_address_1();
let event = EthereumEvent::TransfersToNamada {
Expand Down Expand Up @@ -821,7 +817,7 @@ mod tests {
(KeyKind::VotingPower, Some(power)) => {
let power = EpochedVotingPower::try_from_slice(&power)
.expect("Test failed")
.average_voting_power(&wl_storage);
.fractional_stake(&wl_storage);
assert_eq!(power, FractionalVotingPower::HALF);
}
(_, Some(_)) => {}
Expand Down Expand Up @@ -851,7 +847,7 @@ mod tests {
(KeyKind::VotingPower, Some(power)) => {
let power = EpochedVotingPower::try_from_slice(&power)
.expect("Test failed")
.average_voting_power(&wl_storage);
.fractional_stake(&wl_storage);
assert_eq!(power, FractionalVotingPower::HALF);
}
(_, Some(_)) => {}
Expand Down
Loading

0 comments on commit fdcea56

Please sign in to comment.