1use crate::ser_bytes_in_hex_string;
2use crate::ser_u256_in_dec_string;
3use crate::Group;
4use crate::TaskType;
5use ethers_core::types::{Address, H256, U256};
6use serde::{Deserialize, Serialize};
7use serde_json::{json, Value};
8use std::fmt::Display;
9use threshold_bls::group::Curve;
10use threshold_bls::serialize::point_to_hex;
11
12pub mod encoder;
13
14#[derive(Serialize, Deserialize, Debug)]
15pub enum LogType {
16 DKGKeyGenerated,
17 NodeRegistered,
18 NodeRegisterFailed,
19 NodeActivated,
20 NodeActivationFailed,
21 TaskReceived,
22 DKGGroupingStarted,
23 DKGGroupingFinished,
24 DKGGroupingAborted,
25 DKGGroupingFailed,
26 DKGGroupingCommitted,
27 DKGGroupingCommitFailed,
28 DKGGroupingAvailable,
29 DKGGroupingTwisted,
30 DKGGroupingMemberMisMatch,
31 DKGPostProcessFinished,
32 DKGPostProcessGroupRelayFinished,
33 PartialSignatureFinished,
34 PartialSignatureFailed,
35 PartialSignatureSent,
36 PartialSignatureSendingRejected,
37 PartialSignatureSendingFailed,
38 AggregatedSignatureFinished,
39 AggregatedSignatureFailed,
40 FulfillmentFinished,
41 FulfillmentFailed,
42 ListenerInterrupted,
43}
44
45#[derive(Serialize, Deserialize, Debug)]
46pub struct Payload<'a> {
47 pub log_type: LogType,
48 pub message: &'a str,
49 pub chain_id: Option<usize>,
50 pub group_log: Option<GroupLog>,
51 pub task_log: Option<TaskLog<'a>>,
52 pub transaction_receipt_log: Option<TransactionReceiptLog>,
53}
54
55impl Display for Payload<'_> {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 json!(self).fmt(f)
58 }
59}
60
61#[derive(Serialize, Deserialize, Debug)]
62pub struct GroupLog {
63 pub index: usize,
64 pub epoch: usize,
65 pub size: usize,
66 pub threshold: usize,
67 pub state: bool,
68 pub public_key: Option<String>,
69 pub members: Vec<MemberLog>,
70 pub committers: Vec<Address>,
71 pub relayed_chain_id: Option<usize>,
72}
73
74#[derive(Serialize, Deserialize, Debug)]
75pub struct MemberLog {
76 pub index: usize,
77 pub id_address: Address,
78 pub rpc_endpoint: Option<String>,
79 pub partial_public_key: Option<String>,
80}
81
82impl<C: Curve> From<&Group<C>> for GroupLog {
83 fn from(group: &Group<C>) -> Self {
84 GroupLog {
85 index: group.index,
86 epoch: group.epoch,
87 size: group.size,
88 threshold: group.threshold,
89 state: group.state,
90 public_key: group.public_key.as_ref().map(point_to_hex),
91 members: group
92 .members
93 .iter()
94 .map(|(id_address, member)| MemberLog {
95 index: member.index,
96 id_address: *id_address,
97 rpc_endpoint: member.rpc_endpoint.clone(),
98 partial_public_key: member.partial_public_key.as_ref().map(point_to_hex),
99 })
100 .collect(),
101 committers: group.committers.clone(),
102 relayed_chain_id: None,
103 }
104 }
105}
106
107#[derive(Serialize, Deserialize, Debug)]
108pub struct TaskLog<'a> {
109 #[serde(serialize_with = "ser_bytes_in_hex_string")]
110 pub request_id: &'a [u8],
111 pub task_type: TaskType,
112 pub task_json: Value,
113 pub committer_id_address: Option<Address>,
114}
115
116#[derive(Serialize, Deserialize, Debug)]
117pub struct TransactionReceiptLog {
118 pub transaction_hash: H256,
119 #[serde(serialize_with = "ser_u256_in_dec_string")]
120 pub gas_used: U256,
121 #[serde(serialize_with = "ser_u256_in_dec_string")]
122 pub effective_gas_price: U256,
123}
124
125pub fn build_general_payload(log_type: LogType, message: &str, chain_id: Option<usize>) -> Payload {
126 Payload {
127 log_type,
128 message,
129 chain_id,
130 group_log: None,
131 task_log: None,
132 transaction_receipt_log: None,
133 }
134}
135
136pub fn build_group_related_payload<'a, C: Curve>(
137 log_type: LogType,
138 message: &'a str,
139 chain_id: usize,
140 group: &'a Group<C>,
141) -> Payload<'a> {
142 Payload {
143 log_type,
144 message,
145 chain_id: Some(chain_id),
146 group_log: Some(group.into()),
147 task_log: None,
148 transaction_receipt_log: None,
149 }
150}
151
152pub fn build_task_related_payload<'a>(
153 log_type: LogType,
154 message: &'a str,
155 chain_id: usize,
156 request_id: &'a [u8],
157 task_type: TaskType,
158 task_json: Value,
159 committer_id_address: Option<Address>,
160) -> Payload<'a> {
161 Payload {
162 log_type,
163 message,
164 chain_id: Some(chain_id),
165 group_log: None,
166 task_log: Some(TaskLog {
167 request_id,
168 task_type,
169 task_json,
170 committer_id_address,
171 }),
172 transaction_receipt_log: None,
173 }
174}
175
176pub fn build_transaction_receipt_payload(
177 log_type: LogType,
178 message: &str,
179 chain_id: usize,
180 transaction_hash: H256,
181 gas_used: U256,
182 effective_gas_price: U256,
183) -> Payload {
184 Payload {
185 log_type,
186 message,
187 chain_id: Some(chain_id),
188 group_log: None,
189 task_log: None,
190 transaction_receipt_log: Some(TransactionReceiptLog {
191 transaction_hash,
192 gas_used,
193 effective_gas_price,
194 }),
195 }
196}
197
198#[allow(clippy::too_many_arguments)]
199pub fn build_group_related_transaction_receipt_payload<'a, C: Curve>(
200 log_type: LogType,
201 message: &'a str,
202 chain_id: usize,
203 group: &'a Group<C>,
204 relayed_chain_id: Option<usize>,
205 transaction_hash: H256,
206 gas_used: U256,
207 effective_gas_price: U256,
208) -> Payload<'a> {
209 let mut group_log: GroupLog = group.into();
210 group_log.relayed_chain_id = relayed_chain_id;
211
212 Payload {
213 log_type,
214 message,
215 chain_id: Some(chain_id),
216 group_log: Some(group_log),
217 task_log: None,
218 transaction_receipt_log: Some(TransactionReceiptLog {
219 transaction_hash,
220 gas_used,
221 effective_gas_price,
222 }),
223 }
224}
225
226#[allow(clippy::too_many_arguments)]
227pub fn build_task_related_transaction_receipt_payload<'a>(
228 log_type: LogType,
229 message: &'a str,
230 chain_id: usize,
231 request_id: &'a [u8],
232 task_type: TaskType,
233 task_json: Value,
234 transaction_hash: H256,
235 gas_used: U256,
236 effective_gas_price: U256,
237) -> Payload<'a> {
238 Payload {
239 log_type,
240 message,
241 chain_id: Some(chain_id),
242 group_log: None,
243 task_log: Some(TaskLog {
244 request_id,
245 task_type,
246 task_json,
247 committer_id_address: None,
248 }),
249 transaction_receipt_log: Some(TransactionReceiptLog {
250 transaction_hash,
251 gas_used,
252 effective_gas_price,
253 }),
254 }
255}
256
257#[cfg(test)]
258mod test {
259 use crate::BLSTaskType;
260
261 use super::*;
262
263 #[test]
264 fn test_build_json_payload() {
265 let payload = build_general_payload(LogType::TaskReceived, "Request received", Some(1));
266 println!("{}", payload);
267
268 let request_id = vec![0, 1, 2, 3, 4, 5, 6, 7];
269
270 let payload = build_task_related_payload(
271 LogType::TaskReceived,
272 "Request received",
273 1,
274 &request_id,
275 TaskType::BLS(BLSTaskType::Randomness),
276 json!({ "task": "Randomness" }),
277 None,
278 );
279 println!("{}", payload);
280
281 let payload = build_task_related_transaction_receipt_payload(
282 LogType::FulfillmentFinished,
283 "Fulfillment finished",
284 1,
285 &request_id,
286 TaskType::BLS(BLSTaskType::Randomness),
287 json!({ "task": "Randomness" }),
288 H256::zero(),
289 U256::zero(),
290 U256::zero(),
291 );
292 println!("{}", payload);
293 }
294}