espresso_types/v0/v0_4/
state.rs1use std::collections::HashSet;
2
3use alloy::primitives::{Address, U256};
4use derive_more::{Display, From, Into};
5use hotshot_contract_adapter::reward::{RewardAuthData, RewardClaimInput};
6use jf_merkle_tree_compat::{
7 universal_merkle_tree::UniversalMerkleTree, MerkleTreeScheme, UniversalMerkleTreeScheme,
8};
9use serde::{Deserialize, Serialize};
10
11use super::FeeAccount;
12use crate::{
13 v0::sparse_mt::{Keccak256Hasher, KeccakNode},
14 v0_3::{RewardAccountV1, RewardAmount},
15};
16
17pub const REWARD_MERKLE_TREE_V2_HEIGHT: usize = 160;
18pub const REWARD_MERKLE_TREE_V2_ARITY: usize = 2;
19
20pub type RewardMerkleCommitmentV2 = <RewardMerkleTreeV2 as MerkleTreeScheme>::Commitment;
21
22pub type RewardMerkleTreeV2 = UniversalMerkleTree<
23 RewardAmount,
24 Keccak256Hasher,
25 RewardAccountV2,
26 REWARD_MERKLE_TREE_V2_ARITY,
27 KeccakNode,
28>;
29#[derive(
34 Default,
35 Hash,
36 Copy,
37 Clone,
38 Debug,
39 Display,
40 Deserialize,
41 Serialize,
42 PartialEq,
43 Eq,
44 PartialOrd,
45 Ord,
46 From,
47 Into,
48)]
49#[display("{_0}")]
50pub struct RewardAccountV2(pub Address);
51
52impl From<RewardAccountV2> for RewardAccountV1 {
53 fn from(account: RewardAccountV2) -> Self {
54 RewardAccountV1(account.0)
55 }
56}
57
58impl From<RewardAccountV1> for RewardAccountV2 {
59 fn from(account: RewardAccountV1) -> Self {
60 RewardAccountV2(account.0)
61 }
62}
63
64#[derive(Clone, Debug, Deserialize, Serialize)]
69pub struct RewardAccountProofV2 {
70 pub account: Address,
71 pub proof: RewardMerkleProofV2,
72}
73
74#[derive(Clone, Debug, Deserialize, Serialize)]
75pub enum RewardMerkleProofV2 {
76 Presence(<RewardMerkleTreeV2 as MerkleTreeScheme>::MembershipProof),
77 Absence(<RewardMerkleTreeV2 as UniversalMerkleTreeScheme>::NonMembershipProof),
78}
79
80#[derive(Clone, Debug, Serialize, Deserialize)]
81pub struct RewardAccountQueryDataV2 {
82 pub balance: U256,
83 pub proof: RewardAccountProofV2,
84}
85
86#[derive(Debug, thiserror::Error)]
87pub enum RewardClaimError {
88 #[error("Zero reward balance")]
89 ZeroRewardError,
90 #[error("Failed to convert proof: {0}")]
91 ProofConversionError(#[from] anyhow::Error),
92}
93
94impl RewardAccountQueryDataV2 {
95 pub fn to_reward_claim_input(self) -> Result<RewardClaimInput, RewardClaimError> {
100 if self.balance == U256::ZERO {
101 return Err(RewardClaimError::ZeroRewardError);
102 }
103
104 let account_proof = match self.proof.proof {
105 RewardMerkleProofV2::Presence(_) => self.proof,
106 RewardMerkleProofV2::Absence(_) => {
107 return Err(RewardClaimError::ZeroRewardError);
108 },
109 };
110
111 Ok(RewardClaimInput {
112 lifetime_rewards: self.balance,
113 auth_data: RewardAuthData::new(account_proof.try_into()?).into(),
114 })
115 }
116}
117
118#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
119pub struct Delta {
120 pub fees_delta: HashSet<FeeAccount>,
121 pub rewards_delta: HashSet<RewardAccountV2>,
122}