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, RewardAuthRootInputs, 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(
96 self,
97 auth_root_inputs: RewardAuthRootInputs,
98 ) -> Result<RewardClaimInput, RewardClaimError> {
99 if self.balance == U256::ZERO {
100 return Err(RewardClaimError::ZeroRewardError);
101 }
102
103 let account_proof = match self.proof.proof {
104 RewardMerkleProofV2::Presence(_) => self.proof,
105 RewardMerkleProofV2::Absence(_) => {
106 return Err(RewardClaimError::ZeroRewardError);
107 },
108 };
109
110 Ok(RewardClaimInput {
111 lifetime_rewards: self.balance,
112 auth_data: RewardAuthData::new(account_proof.try_into()?, auth_root_inputs).into(),
113 })
114 }
115}
116
117#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
118pub struct Delta {
119 pub fees_delta: HashSet<FeeAccount>,
120 pub rewards_delta: HashSet<RewardAccountV2>,
121}