Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tzemanovic committed Aug 11, 2022
1 parent 13623c0 commit 5248e75
Show file tree
Hide file tree
Showing 19 changed files with 898 additions and 407 deletions.
1 change: 1 addition & 0 deletions shared/src/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod native_vp;
pub mod parameters;
pub mod pos;
pub mod storage;
pub mod storage_api;
pub mod treasury;
pub mod tx_env;
pub mod vp_env;
157 changes: 157 additions & 0 deletions shared/src/ledger/native_vp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::cell::RefCell;
use std::collections::BTreeSet;

use super::storage_api::{self, ResultExt, StorageRead};
pub use super::vp_env::VpEnv;
use crate::ledger::gas::VpGasMeter;
use crate::ledger::storage::write_log::WriteLog;
Expand Down Expand Up @@ -72,6 +73,30 @@ where
pub cache_access: std::marker::PhantomData<CA>,
}

/// Read access to the prior storage (state before tx execution) via
/// [`trait@StorageRead`].
#[derive(Debug)]
pub struct CtxPreStorageRead<'b, 'a: 'b, DB, H, CA>
where
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
CA: WasmCacheAccess,
{
ctx: &'b Ctx<'a, DB, H, CA>,
}

/// Read access to the posterior storage (state after tx execution) via
/// [`trait@StorageRead`].
#[derive(Debug)]
pub struct CtxPostStorageRead<'f, 'a: 'f, DB, H, CA>
where
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
CA: WasmCacheAccess,
{
ctx: &'f Ctx<'a, DB, H, CA>,
}

impl<'a, DB, H, CA> Ctx<'a, DB, H, CA>
where
DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
Expand Down Expand Up @@ -111,6 +136,138 @@ where
pub fn add_gas(&self, used_gas: u64) -> Result<(), vp_env::RuntimeError> {
vp_env::add_gas(&mut *self.gas_meter.borrow_mut(), used_gas)
}

/// Read access to the prior storage (state before tx execution)
/// via [`trait@StorageRead`].
pub fn pre<'b>(&'b self) -> CtxPreStorageRead<'b, 'a, DB, H, CA> {
CtxPreStorageRead { ctx: self }
}

/// Read access to the posterior storage (state after tx execution)
/// via [`trait@StorageRead`].
pub fn post<'b>(&'b self) -> CtxPostStorageRead<'b, 'a, DB, H, CA> {
CtxPostStorageRead { ctx: self }
}
}

impl<'f, 'a, DB, H, CA> StorageRead for CtxPreStorageRead<'f, 'a, DB, H, CA>
where
DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + StorageHasher,
CA: 'static + WasmCacheAccess,
{
type PrefixIter = <DB as storage::DBIter<'a>>::PrefixIter;

fn read<T: borsh::BorshDeserialize>(
&self,
key: &crate::types::storage::Key,
) -> Result<Option<T>, storage_api::Error> {
self.ctx.read_pre(key).into_storage_result()
}

fn read_bytes(
&self,
key: &crate::types::storage::Key,
) -> Result<Option<Vec<u8>>, storage_api::Error> {
self.ctx.read_bytes_pre(key).into_storage_result()
}

fn has_key(
&self,
key: &crate::types::storage::Key,
) -> Result<bool, storage_api::Error> {
self.ctx.has_key_pre(key).into_storage_result()
}

fn iter_prefix(
&self,
prefix: &crate::types::storage::Key,
) -> Result<Self::PrefixIter, storage_api::Error> {
self.ctx.iter_prefix(prefix).into_storage_result()
}

fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, storage_api::Error> {
self.ctx.iter_pre_next(iter).into_storage_result()
}

fn get_chain_id(&self) -> Result<String, storage_api::Error> {
self.ctx.get_chain_id().into_storage_result()
}

fn get_block_height(&self) -> Result<BlockHeight, storage_api::Error> {
self.ctx.get_block_height().into_storage_result()
}

fn get_block_hash(&self) -> Result<BlockHash, storage_api::Error> {
self.ctx.get_block_hash().into_storage_result()
}

fn get_block_epoch(&self) -> Result<Epoch, storage_api::Error> {
self.ctx.get_block_epoch().into_storage_result()
}
}

impl<'f, 'a, DB, H, CA> StorageRead for CtxPostStorageRead<'f, 'a, DB, H, CA>
where
DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + StorageHasher,
CA: 'static + WasmCacheAccess,
{
type PrefixIter = <DB as storage::DBIter<'a>>::PrefixIter;

fn read<T: borsh::BorshDeserialize>(
&self,
key: &crate::types::storage::Key,
) -> Result<Option<T>, storage_api::Error> {
self.ctx.read_post(key).into_storage_result()
}

fn read_bytes(
&self,
key: &crate::types::storage::Key,
) -> Result<Option<Vec<u8>>, storage_api::Error> {
self.ctx.read_bytes_post(key).into_storage_result()
}

fn has_key(
&self,
key: &crate::types::storage::Key,
) -> Result<bool, storage_api::Error> {
self.ctx.has_key_post(key).into_storage_result()
}

fn iter_prefix(
&self,
prefix: &crate::types::storage::Key,
) -> Result<Self::PrefixIter, storage_api::Error> {
self.ctx.iter_prefix(prefix).into_storage_result()
}

fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, storage_api::Error> {
self.ctx.iter_post_next(iter).into_storage_result()
}

fn get_chain_id(&self) -> Result<String, storage_api::Error> {
self.ctx.get_chain_id().into_storage_result()
}

fn get_block_height(&self) -> Result<BlockHeight, storage_api::Error> {
self.ctx.get_block_height().into_storage_result()
}

fn get_block_hash(&self) -> Result<BlockHash, storage_api::Error> {
self.ctx.get_block_hash().into_storage_result()
}

fn get_block_epoch(&self) -> Result<Epoch, storage_api::Error> {
self.ctx.get_block_epoch().into_storage_result()
}
}

impl<'a, DB, H, CA> VpEnv for Ctx<'a, DB, H, CA>
Expand Down
136 changes: 136 additions & 0 deletions shared/src/ledger/pos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,139 @@ impl From<namada_proof_of_stake::types::Epoch> for Epoch {
Epoch(epoch)
}
}

#[macro_use]
mod macros {
/// Implement `PosReadOnly` for a type that implements
/// [`trait@crate::ledger::storage_api::StorageRead`].
///
/// Excuse the horrible syntax - we haven't found a better way to use this
/// for native_vp `CtxPreStorageRead`/`CtxPostStorageRead`, which have
/// generics and explicit lifetimes.
///
/// # Examples
///
/// ```ignore
/// impl_pos_read_only! { impl PosReadOnly for X }
/// ```
#[macro_export]
macro_rules! impl_pos_read_only {
(
// Type error type has to be declared before the impl.
// This error type must `impl From<storage_api::Error> for $error`.
type $error:tt = $err_ty:ty ;
// Matches anything, so that we can use lifetimes and generic types.
// This expects `impl(<.*>)? PoSReadOnly for $ty(<.*>)?`.
$( $any:tt )* )
=> {
$( $any )*
{
type Address = $crate::types::address::Address;
// type Error = $crate::ledger::native_vp::Error;
type $error = $err_ty;
type PublicKey = $crate::types::key::common::PublicKey;
type TokenAmount = $crate::types::token::Amount;
type TokenChange = $crate::types::token::Change;

const POS_ADDRESS: Self::Address = $crate::ledger::pos::ADDRESS;

fn staking_token_address() -> Self::Address {
$crate::ledger::pos::staking_token_address()
}

fn read_pos_params(&self) -> std::result::Result<PosParams, Self::Error> {
let value = $crate::ledger::storage_api::StorageRead::read_bytes(self, &params_key())?.unwrap();
Ok($crate::ledger::storage::types::decode(value).unwrap())
}

fn read_validator_staking_reward_address(
&self,
key: &Self::Address,
) -> std::result::Result<Option<Self::Address>, Self::Error> {
let value = $crate::ledger::storage_api::StorageRead::read_bytes(
self,
&validator_staking_reward_address_key(key),
)?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_validator_consensus_key(
&self,
key: &Self::Address,
) -> std::result::Result<Option<ValidatorConsensusKeys>, Self::Error> {
let value =
$crate::ledger::storage_api::StorageRead::read_bytes(self, &validator_consensus_key_key(key))?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_validator_state(
&self,
key: &Self::Address,
) -> std::result::Result<Option<ValidatorStates>, Self::Error> {
let value = $crate::ledger::storage_api::StorageRead::read_bytes(self, &validator_state_key(key))?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_validator_total_deltas(
&self,
key: &Self::Address,
) -> std::result::Result<Option<ValidatorTotalDeltas>, Self::Error> {
let value =
$crate::ledger::storage_api::StorageRead::read_bytes(self, &validator_total_deltas_key(key))?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_validator_voting_power(
&self,
key: &Self::Address,
) -> std::result::Result<Option<ValidatorVotingPowers>, Self::Error> {
let value =
$crate::ledger::storage_api::StorageRead::read_bytes(self, &validator_voting_power_key(key))?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_validator_slashes(
&self,
key: &Self::Address,
) -> std::result::Result<Vec<types::Slash>, Self::Error> {
let value = $crate::ledger::storage_api::StorageRead::read_bytes(self, &validator_slashes_key(key))?;
Ok(value
.map(|value| $crate::ledger::storage::types::decode(value).unwrap())
.unwrap_or_default())
}

fn read_bond(
&self,
key: &BondId,
) -> std::result::Result<Option<Bonds>, Self::Error> {
let value = $crate::ledger::storage_api::StorageRead::read_bytes(self, &bond_key(key))?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_unbond(
&self,
key: &BondId,
) -> std::result::Result<Option<Unbonds>, Self::Error> {
let value = $crate::ledger::storage_api::StorageRead::read_bytes(self, &unbond_key(key))?;
Ok(value.map(|value| $crate::ledger::storage::types::decode(value).unwrap()))
}

fn read_validator_set(
&self,
) -> std::result::Result<ValidatorSets, Self::Error> {
let value =
$crate::ledger::storage_api::StorageRead::read_bytes(self, &validator_set_key())?.unwrap();
Ok($crate::ledger::storage::types::decode(value).unwrap())
}

fn read_total_voting_power(
&self,
) -> std::result::Result<TotalVotingPowers, Self::Error> {
let value =
$crate::ledger::storage_api::StorageRead::read_bytes(self, &total_voting_power_key())?.unwrap();
Ok($crate::ledger::storage::types::decode(value).unwrap())
}
}
}
}
}
Loading

0 comments on commit 5248e75

Please sign in to comment.