namada_core/
ethereum_structs.rs

1//! Ethereum bridge struct re-exports and types to do with ethereum.
2
3use std::fmt;
4use std::io::Read;
5use std::num::NonZeroU64;
6use std::ops::Deref;
7
8use borsh::{BorshDeserialize, BorshSerialize};
9pub use ethbridge_structs::*;
10use num256::Uint256;
11use serde::{Deserialize, Serialize};
12
13/// This type must be able to represent any valid Ethereum block height. It must
14/// also be Borsh serializeable, so that it can be stored in blockchain storage.
15///
16/// In Ethereum, the type for block height is an arbitrary precision integer - see <https://github.com/ethereum/go-ethereum/blob/v1.10.26/core/types/block.go#L79>.
17#[derive(
18    Default,
19    Debug,
20    Clone,
21    Eq,
22    PartialEq,
23    Ord,
24    PartialOrd,
25    Hash,
26    Serialize,
27    Deserialize,
28)]
29#[repr(transparent)]
30pub struct BlockHeight(Uint256);
31
32impl BlockHeight {
33    /// Get the next block height.
34    ///
35    /// # Panic
36    ///
37    /// Panics on overflow.
38    pub fn next(&self) -> Self {
39        self.unchecked_add(1_u64)
40    }
41
42    /// Unchecked epoch addition.
43    ///
44    /// # Panic
45    ///
46    /// Panics on overflow. Care must be taken to only use this with trusted
47    /// values that are known to be in a limited range (e.g. system parameters
48    /// but not e.g. transaction variables).
49    pub fn unchecked_add(&self, rhs: impl Into<BlockHeight>) -> Self {
50        use num_traits::CheckedAdd;
51        Self(
52            self.0
53                .checked_add(&rhs.into())
54                .expect("Block height addition shouldn't overflow"),
55        )
56    }
57}
58
59impl fmt::Display for BlockHeight {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        write!(f, "{}", self.0)
62    }
63}
64
65impl From<u64> for BlockHeight {
66    fn from(value: u64) -> Self {
67        Self(Uint256::from(value))
68    }
69}
70
71impl From<NonZeroU64> for BlockHeight {
72    fn from(value: NonZeroU64) -> Self {
73        Self(Uint256::from(value.get()))
74    }
75}
76
77impl From<Uint256> for BlockHeight {
78    fn from(value: Uint256) -> Self {
79        Self(value)
80    }
81}
82
83impl From<BlockHeight> for Uint256 {
84    fn from(BlockHeight(value): BlockHeight) -> Self {
85        value
86    }
87}
88
89impl<'a> From<&'a BlockHeight> for &'a Uint256 {
90    fn from(BlockHeight(height): &'a BlockHeight) -> Self {
91        height
92    }
93}
94
95impl Deref for BlockHeight {
96    type Target = Uint256;
97
98    fn deref(&self) -> &Self::Target {
99        &self.0
100    }
101}
102
103impl BorshSerialize for BlockHeight {
104    fn serialize<W: std::io::Write>(
105        &self,
106        writer: &mut W,
107    ) -> std::io::Result<()> {
108        let be = self.0.to_be_bytes();
109        BorshSerialize::serialize(&be, writer)
110    }
111}
112
113impl BorshDeserialize for BlockHeight {
114    fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self> {
115        let be: Vec<u8> = BorshDeserialize::deserialize_reader(reader)?;
116        Ok(Self(Uint256::from_be_bytes(&be)))
117    }
118}