arpa_core/log/
mod.rs

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}