Skip to content

Commit

Permalink
Merge pull request #1006 from anoma/bat/ethbridge/ethbridge-queries
Browse files Browse the repository at this point in the history
Add EthBridgeQueries trait for storage
  • Loading branch information
batconjurer authored Jan 12, 2023
2 parents 1361088 + 448e1ac commit dc2586d
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 131 deletions.
4 changes: 2 additions & 2 deletions apps/src/lib/node/ledger/shell/prepare_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#[cfg(not(feature = "abcipp"))]
use index_set::vec::VecIndexSet;
use namada::core::hints;
use namada::ledger::pos::PosQueries;
#[cfg(feature = "abcipp")]
use namada::ledger::pos::SendValsetUpd;
use namada::ledger::eth_bridge::{EthBridgeQueries, SendValsetUpd};
use namada::ledger::pos::PosQueries;
use namada::ledger::storage::traits::StorageHasher;
use namada::ledger::storage::{DBIter, DB};
use namada::proto::Tx;
Expand Down
3 changes: 2 additions & 1 deletion apps/src/lib/node/ledger/shell/process_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
use data_encoding::HEXUPPER;
use namada::core::hints;
use namada::core::ledger::storage::Storage;
use namada::ledger::pos::{PosQueries, SendValsetUpd};
use namada::ledger::eth_bridge::{EthBridgeQueries, SendValsetUpd};
use namada::ledger::pos::PosQueries;
use namada::types::transaction::protocol::ProtocolTxType;
#[cfg(feature = "abcipp")]
use namada::types::voting_power::FractionalVotingPower;
Expand Down
3 changes: 2 additions & 1 deletion apps/src/lib/node/ledger/shell/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ where
#[cfg(test)]
#[cfg(not(feature = "abcipp"))]
mod test_queries {
use namada::ledger::pos::{PosQueries, SendValsetUpd};
use namada::ledger::eth_bridge::{EthBridgeQueries, SendValsetUpd};
use namada::ledger::pos::PosQueries;
use namada::types::storage::Epoch;

use super::*;
Expand Down
4 changes: 3 additions & 1 deletion apps/src/lib/node/ledger/shell/vote_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ pub mod val_set_update;
use borsh::BorshDeserialize;
#[cfg(not(feature = "abcipp"))]
use index_set::vec::VecIndexSet;
use namada::ledger::pos::{PosQueries, SendValsetUpd};
use namada::ledger::eth_bridge::{EthBridgeQueries, SendValsetUpd};
#[cfg(feature = "abcipp")]
use namada::ledger::pos::PosQueries;
use namada::proto::Signed;
use namada::types::transaction::protocol::ProtocolTxType;
#[cfg(feature = "abcipp")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ mod test_vote_extensions {
#[cfg(feature = "abcipp")]
#[cfg(feature = "abcipp")]
use borsh::BorshSerialize;
use namada::ledger::eth_bridge::EthBridgeQueries;
use namada::ledger::pos;
use namada::ledger::pos::namada_proof_of_stake::PosBase;
use namada::ledger::pos::PosQueries;
Expand Down
141 changes: 141 additions & 0 deletions ethereum_bridge/src/storage/eth_bridge_queries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use namada_core::ledger::storage;
use namada_core::ledger::storage::Storage;
use namada_core::types::address::Address;
use namada_core::types::ethereum_events::EthAddress;
use namada_core::types::storage::Epoch;
use namada_core::types::token;
use namada_core::types::vote_extensions::validator_set_update::EthAddrBook;
use namada_proof_of_stake::pos_queries::PosQueries;
use namada_proof_of_stake::PosBase;

/// This enum is used as a parameter to
/// [`PosQueries::can_send_validator_set_update`].
pub enum SendValsetUpd {
/// Check if it is possible to send a validator set update
/// vote extension at the current block height.
Now,
/// Check if it is possible to send a validator set update
/// vote extension at the previous block height.
AtPrevHeight,
}

pub trait EthBridgeQueries {
/// Determines if it is possible to send a validator set update vote
/// extension at the provided [`BlockHeight`] in [`SendValsetUpd`].
fn can_send_validator_set_update(&self, can_send: SendValsetUpd) -> bool;

/// For a given Namada validator, return its corresponding Ethereum bridge
/// address.
fn get_ethbridge_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress>;

/// For a given Namada validator, return its corresponding Ethereum
/// governance address.
fn get_ethgov_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress>;

/// Extension of [`Self::get_active_validators`], which additionally returns
/// all Ethereum addresses of some validator.
fn get_active_eth_addresses<'db>(
&'db self,
epoch: Option<Epoch>,
) -> Box<dyn Iterator<Item = (EthAddrBook, Address, token::Amount)> + 'db>;
}

impl<D, H> EthBridgeQueries for Storage<D, H>
where
D: storage::DB + for<'iter> storage::DBIter<'iter>,
H: storage::StorageHasher,
{
#[cfg(feature = "abcipp")]
#[inline]
fn can_send_validator_set_update(&self, _can_send: SendValsetUpd) -> bool {
// TODO: implement this method for ABCI++; should only be able to send
// a validator set update at the second block of an epoch
false
}

#[cfg(not(feature = "abcipp"))]
#[inline]
fn can_send_validator_set_update(&self, can_send: SendValsetUpd) -> bool {
if matches!(can_send, SendValsetUpd::AtPrevHeight) {
// when checking vote extensions in Prepare
// and ProcessProposal, we simply return true
true
} else {
// offset of 1 => are we at the 2nd
// block within the epoch?
self.is_deciding_offset_within_epoch(1)
}
}

#[inline]
fn get_ethbridge_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress> {
let epoch = epoch.unwrap_or_else(|| self.get_current_epoch().0);
self.read_validator_eth_hot_key(validator)
.as_ref()
.and_then(|epk| epk.get(epoch).and_then(|pk| pk.try_into().ok()))
}

#[inline]
fn get_ethgov_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress> {
let epoch = epoch.unwrap_or_else(|| self.get_current_epoch().0);
self.read_validator_eth_cold_key(validator)
.as_ref()
.and_then(|epk| epk.get(epoch).and_then(|pk| pk.try_into().ok()))
}

#[inline]
fn get_active_eth_addresses<'db>(
&'db self,
epoch: Option<Epoch>,
) -> Box<dyn Iterator<Item = (EthAddrBook, Address, token::Amount)> + 'db>
{
let epoch = epoch.unwrap_or_else(|| self.get_current_epoch().0);
Box::new(self.get_active_validators(Some(epoch)).into_iter().map(
move |validator| {
let hot_key_addr = self
.get_ethbridge_from_namada_addr(
&validator.address,
Some(epoch),
)
.expect(
"All Namada validators should have an Ethereum bridge \
key",
);
let cold_key_addr = self
.get_ethgov_from_namada_addr(
&validator.address,
Some(epoch),
)
.expect(
"All Namada validators should have an Ethereum \
governance key",
);
let eth_addr_book = EthAddrBook {
hot_key_addr,
cold_key_addr,
};
(
eth_addr_book,
validator.address,
validator.bonded_stake.into(),
)
},
))
}
}
2 changes: 2 additions & 0 deletions ethereum_bridge/src/storage/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! Functionality for accessing the storage subspace
pub use namada_core::ledger::eth_bridge::storage::bridge_pool;
pub mod eth_bridge_queries;
pub mod vote_tallies;

pub use namada_core::ledger::eth_bridge::storage::{wrapped_erc20s, *};
126 changes: 0 additions & 126 deletions proof_of_stake/src/pos_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ use namada_core::ledger::storage::Storage;
use namada_core::ledger::{storage, storage_api};
use namada_core::types::address::Address;
use namada_core::types::chain::ProposalBytes;
use namada_core::types::ethereum_events::EthAddress;
use namada_core::types::key::dkg_session_keys::DkgPublicKey;
use namada_core::types::storage::{BlockHeight, Epoch};
use namada_core::types::transaction::EllipticCurve;
use namada_core::types::vote_extensions::validator_set_update::EthAddrBook;
use namada_core::types::{key, token};
use thiserror::Error;

Expand Down Expand Up @@ -56,17 +54,6 @@ pub enum Error {
/// Result type returned by [`PosQueries`] operations.
pub type Result<T> = ::std::result::Result<T, Error>;

/// This enum is used as a parameter to
/// [`PosQueries::can_send_validator_set_update`].
pub enum SendValsetUpd {
/// Check if it is possible to send a validator set update
/// vote extension at the current block height.
Now,
/// Check if it is possible to send a validator set update
/// vote extension at the previous block height.
AtPrevHeight,
}

/// Methods used to query blockchain proof-of-stake related state,
/// such as the currently active set of validators.
pub trait PosQueries {
Expand Down Expand Up @@ -117,10 +104,6 @@ pub trait PosQueries {
epoch: Option<Epoch>,
) -> Result<Address>;

/// Determines if it is possible to send a validator set update vote
/// extension at the provided [`BlockHeight`] in [`SendValsetUpd`].
fn can_send_validator_set_update(&self, can_send: SendValsetUpd) -> bool;

/// Check if we are at a given [`BlockHeight`] offset, `height_offset`,
/// within the current [`Epoch`].
fn is_deciding_offset_within_epoch(&self, height_offset: u64) -> bool;
Expand All @@ -131,29 +114,6 @@ pub trait PosQueries {
/// Retrieves the [`BlockHeight`] that is currently being decided.
fn get_current_decision_height(&self) -> BlockHeight;

/// For a given Namada validator, return its corresponding Ethereum bridge
/// address.
fn get_ethbridge_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress>;

/// For a given Namada validator, return its corresponding Ethereum
/// governance address.
fn get_ethgov_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress>;

/// Extension of [`Self::get_active_validators`], which additionally returns
/// all Ethereum addresses of some validator.
fn get_active_eth_addresses<'db>(
&'db self,
epoch: Option<Epoch>,
) -> Box<dyn Iterator<Item = (EthAddrBook, Address, token::Amount)> + 'db>;

/// Retrieve the `max_proposal_bytes` consensus parameter from storage.
fn get_max_proposal_bytes(&self) -> ProposalBytes;
}
Expand Down Expand Up @@ -304,28 +264,6 @@ where
})
}

#[cfg(feature = "abcipp")]
#[inline]
fn can_send_validator_set_update(&self, _can_send: SendValsetUpd) -> bool {
// TODO: implement this method for ABCI++; should only be able to send
// a validator set update at the second block of an epoch
false
}

#[cfg(not(feature = "abcipp"))]
#[inline]
fn can_send_validator_set_update(&self, can_send: SendValsetUpd) -> bool {
if matches!(can_send, SendValsetUpd::AtPrevHeight) {
// when checking vote extensions in Prepare
// and ProcessProposal, we simply return true
true
} else {
// offset of 1 => are we at the 2nd
// block within the epoch?
self.is_deciding_offset_within_epoch(1)
}
}

fn is_deciding_offset_within_epoch(&self, height_offset: u64) -> bool {
let current_decision_height = self.get_current_decision_height();

Expand Down Expand Up @@ -361,70 +299,6 @@ where
self.last_height + 1
}

#[inline]
fn get_ethbridge_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress> {
let epoch = epoch.unwrap_or_else(|| self.get_current_epoch().0);
self.read_validator_eth_hot_key(validator)
.as_ref()
.and_then(|epk| epk.get(epoch).and_then(|pk| pk.try_into().ok()))
}

#[inline]
fn get_ethgov_from_namada_addr(
&self,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<EthAddress> {
let epoch = epoch.unwrap_or_else(|| self.get_current_epoch().0);
self.read_validator_eth_cold_key(validator)
.as_ref()
.and_then(|epk| epk.get(epoch).and_then(|pk| pk.try_into().ok()))
}

#[inline]
fn get_active_eth_addresses<'db>(
&'db self,
epoch: Option<Epoch>,
) -> Box<dyn Iterator<Item = (EthAddrBook, Address, token::Amount)> + 'db>
{
let epoch = epoch.unwrap_or_else(|| self.get_current_epoch().0);
Box::new(self.get_active_validators(Some(epoch)).into_iter().map(
move |validator| {
let hot_key_addr = self
.get_ethbridge_from_namada_addr(
&validator.address,
Some(epoch),
)
.expect(
"All Namada validators should have an Ethereum bridge \
key",
);
let cold_key_addr = self
.get_ethgov_from_namada_addr(
&validator.address,
Some(epoch),
)
.expect(
"All Namada validators should have an Ethereum \
governance key",
);
let eth_addr_book = EthAddrBook {
hot_key_addr,
cold_key_addr,
};
(
eth_addr_book,
validator.address,
validator.bonded_stake.into(),
)
},
))
}

fn get_max_proposal_bytes(&self) -> ProposalBytes {
let key = get_max_proposal_bytes_key();
let (maybe_value, _gas) = self
Expand Down
1 change: 1 addition & 0 deletions shared/src/ledger/eth_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
pub use namada_core::ledger::eth_bridge::storage::wrapped_erc20s;
pub use namada_core::ledger::eth_bridge::{ADDRESS, INTERNAL_ADDRESS};
pub use namada_ethereum_bridge::parameters::*;
pub use namada_ethereum_bridge::storage::eth_bridge_queries::*;

0 comments on commit dc2586d

Please sign in to comment.