secret_toolkit_notification/
structs.rs1use cosmwasm_std::{Addr, Api, Binary, Env, StdError, StdResult, Uint64};
2use minicbor::Encoder;
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6use crate::{cbor_to_std_error, encrypt_notification_data, get_seed, notification_id};
7
8#[derive(Serialize, Debug, Deserialize, Clone)]
9#[cfg_attr(test, derive(Eq, PartialEq))]
10pub struct Notification<T: DirectChannel> {
11 pub notification_for: Addr,
13 pub data: T,
15}
16
17pub trait DirectChannel {
18 const CHANNEL_ID: &'static str;
19 const CDDL_SCHEMA: &'static str;
20 const ELEMENTS: u64;
21 const PAYLOAD_SIZE: usize;
22
23 fn channel_id(&self) -> String {
24 Self::CHANNEL_ID.to_string()
25 }
26
27 fn cddl_schema(&self) -> String {
28 Self::CDDL_SCHEMA.to_string()
29 }
30
31 fn to_cbor(&self, api: &dyn Api) -> StdResult<Vec<u8>> {
32 let mut buffer = vec![0u8; Self::PAYLOAD_SIZE];
34
35 let mut encoder = Encoder::new(&mut buffer[..]);
37
38 encoder.array(Self::ELEMENTS).map_err(cbor_to_std_error)?;
40
41 self.encode_cbor(api, &mut encoder)?;
43
44 Ok(buffer)
46 }
47
48 fn encode_cbor(&self, api: &dyn Api, encoder: &mut Encoder<&mut [u8]>) -> StdResult<()>;
50}
51
52impl<T: DirectChannel> Notification<T> {
53 pub fn new(notification_for: Addr, data: T) -> Self {
54 Notification {
55 notification_for,
56 data,
57 }
58 }
59
60 pub fn to_txhash_notification(
61 &self,
62 api: &dyn Api,
63 env: &Env,
64 secret: &[u8],
65 block_size: Option<usize>,
66 ) -> StdResult<TxHashNotification> {
67 let tx_hash = env
69 .transaction
70 .clone()
71 .ok_or(StdError::generic_err("no tx hash found"))?
72 .hash
73 .to_ascii_uppercase();
74
75 let notification_for_raw = api.addr_canonicalize(self.notification_for.as_str())?;
77
78 let seed = get_seed(¬ification_for_raw, secret)?;
80
81 let id = notification_id(&seed, self.data.channel_id().as_str(), &tx_hash)?;
83
84 let cbor_data = self.data.to_cbor(api)?;
86
87 let encrypted_data = encrypt_notification_data(
89 &env.block.height,
90 &tx_hash,
91 &seed,
92 self.data.channel_id().as_str(),
93 cbor_data,
94 block_size,
95 )?;
96
97 Ok(TxHashNotification { id, encrypted_data })
99 }
100}
101
102#[derive(Serialize, Debug, Deserialize, Clone)]
103#[cfg_attr(test, derive(Eq, PartialEq))]
104pub struct TxHashNotification {
105 pub id: Binary,
106 pub encrypted_data: Binary,
107}
108
109impl TxHashNotification {
110 pub fn id_plaintext(&self) -> String {
111 format!("snip52:{}", self.id.to_base64())
112 }
113
114 pub fn data_plaintext(&self) -> String {
115 self.encrypted_data.to_base64()
116 }
117}
118
119#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
122pub struct ChannelInfoData {
123 pub channel: String,
125 pub mode: String,
127
128 pub answer_id: Option<Binary>,
131
132 pub parameters: Option<BloomParameters>,
135 pub data: Option<Descriptor>,
137
138 pub counter: Option<Uint64>,
141 pub next_id: Option<Binary>,
143
144 pub cddl: Option<String>,
147}
148
149#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
150pub struct BloomParameters {
151 pub m: u32,
152 pub k: u32,
153 pub h: String,
154}
155
156#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
157pub struct Descriptor {
158 pub r#type: String,
159 pub version: String,
160 pub packet_size: u32,
161 pub data: StructDescriptor,
162}
163
164#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
165pub struct StructDescriptor {
166 pub r#type: String,
167 pub label: String,
168 pub members: Vec<FlatDescriptor>,
169}
170
171#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
172pub struct FlatDescriptor {
173 pub r#type: String,
174 pub label: String,
175 pub description: Option<String>,
176}
177
178pub trait GroupChannel<D: DirectChannel> {
179 const CHANNEL_ID: &'static str;
180 const BLOOM_N: usize;
181 const BLOOM_M: u32;
182 const BLOOM_K: u32;
183 const PACKET_SIZE: usize;
184
185 const BLOOM_M_LOG2: u32 = Self::BLOOM_M.ilog2();
186
187 fn build_packet(&self, api: &dyn Api, data: &D) -> StdResult<Vec<u8>>;
188
189 fn notifications(&self) -> &Vec<Notification<D>>;
190}