penumbra_sdk_shielded_pool/component/
fmd.rs1use anyhow::Result;
2use async_trait::async_trait;
3use cnidarium::{StateRead, StateWrite};
4use decaf377_fmd::Clue;
5use penumbra_sdk_proto::{
6 core::component::shielded_pool::v1::{self as pb},
7 StateWriteProto,
8};
9use penumbra_sdk_txhash::TransactionId;
10
11use crate::fmd::state_key;
12
13#[async_trait]
14trait ClueWriteExt: StateWrite {
15 fn put_current_clue_count(&mut self, count: u64) {
16 self.put_raw(
17 state_key::clue_count::current().to_string(),
18 count.to_be_bytes().to_vec(),
19 )
20 }
21
22 fn put_previous_clue_count(&mut self, count: u64) {
23 self.put_raw(
24 state_key::clue_count::previous().to_string(),
25 count.to_be_bytes().to_vec(),
26 )
27 }
28}
29
30impl<T: StateWrite + ?Sized> ClueWriteExt for T {}
31
32#[async_trait]
33trait ClueReadExt: StateRead {
34 async fn get_current_clue_count(&self) -> Result<u64> {
38 Ok(self
39 .get_raw(state_key::clue_count::current())
40 .await?
41 .map(|x| x.as_slice().try_into())
42 .transpose()?
43 .map(u64::from_be_bytes)
44 .unwrap_or(0u64))
45 }
46
47 async fn get_previous_clue_count(&self) -> Result<u64> {
48 Ok(self
49 .get_raw(state_key::clue_count::previous())
50 .await?
51 .map(|x| x.as_slice().try_into())
52 .transpose()?
53 .map(u64::from_be_bytes)
54 .unwrap_or(0u64))
55 }
56}
57
58impl<T: StateRead + ?Sized> ClueReadExt for T {}
59
60#[async_trait]
61pub trait ClueManager: StateRead + StateWrite {
62 async fn record_clue(&mut self, clue: Clue, tx: TransactionId) -> Result<()> {
63 {
64 let count = self.get_current_clue_count().await?;
65 self.put_current_clue_count(count.saturating_add(1));
66 }
67 self.record_proto(pb::EventBroadcastClue {
68 clue: Some(clue.into()),
69 tx: Some(tx.into()),
70 });
71 Ok(())
72 }
73}
74
75impl<T: StateRead + StateWrite> ClueManager for T {}
76
77#[async_trait]
78pub(crate) trait ClueManagerInternal: ClueManager {
79 async fn flush_clue_count(&mut self) -> Result<(u64, u64)> {
81 let previous = self.get_previous_clue_count().await?;
82 let current = self.get_current_clue_count().await?;
83 self.put_previous_clue_count(current);
84 self.put_current_clue_count(0);
85 Ok((previous, current))
86 }
87}
88
89impl<T: ClueManager> ClueManagerInternal for T {}