Skip to content

Commit f345f6a

Browse files
authored
Merge pull request #387 from AdExNetwork/validator-messages-improvements
Validator Messages improvements
2 parents 7621a77 + eb006a3 commit f345f6a

File tree

9 files changed

+301
-94
lines changed

9 files changed

+301
-94
lines changed

adapter/src/ethereum/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub enum KeystoreError {
8484
/// `address` key is missing from the keystore file
8585
AddressMissing,
8686
/// The `address` key in the keystore file is not a valid `ValidatorId`
87-
AddressInvalid(primitives::DomainError),
87+
AddressInvalid(primitives::address::Error),
8888
/// reading the keystore file failed
8989
ReadingFile(std::io::Error),
9090
/// Deserializing the keystore file failed

primitives/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ impl fmt::Display for DomainError {
7474
}
7575
}
7676

77+
impl From<address::Error> for DomainError {
78+
fn from(error: address::Error) -> Self {
79+
Self::InvalidArgument(error.to_string())
80+
}
81+
}
82+
7783
impl error::Error for DomainError {
7884
fn cause(&self) -> Option<&dyn error::Error> {
7985
None

primitives/src/sentry.rs

+113-54
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,112 @@
1-
use crate::targeting::Rules;
2-
use crate::validator::MessageTypes;
3-
use crate::{BigNum, Channel, ChannelId, ValidatorId};
1+
use crate::{
2+
targeting::Rules,
3+
validator::Type as MessageType,
4+
validator::{ApproveState, Heartbeat, MessageTypes, NewState},
5+
BigNum, Channel, ChannelId, ValidatorId,
6+
};
47
use chrono::{DateTime, Utc};
58
use serde::{Deserialize, Serialize};
6-
use std::collections::HashMap;
7-
use std::fmt;
8-
use std::hash::Hash;
9+
use std::{collections::HashMap, fmt, hash::Hash};
910

1011
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
1112
#[serde(rename_all = "camelCase")]
1213
pub struct LastApproved {
1314
/// NewState can be None if the channel is brand new
14-
pub new_state: Option<NewStateValidatorMessage>,
15+
pub new_state: Option<MessageResponse<NewState>>,
1516
/// ApproveState can be None if the channel is brand new
16-
pub approve_state: Option<ApproveStateValidatorMessage>,
17+
pub approve_state: Option<MessageResponse<ApproveState>>,
1718
}
1819

1920
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
20-
pub struct NewStateValidatorMessage {
21+
pub struct MessageResponse<T: MessageType> {
2122
pub from: ValidatorId,
2223
pub received: DateTime<Utc>,
23-
pub msg: MessageTypes,
24+
pub msg: message::Message<T>,
2425
}
2526

26-
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
27-
pub struct ApproveStateValidatorMessage {
28-
pub from: ValidatorId,
29-
pub received: DateTime<Utc>,
30-
pub msg: MessageTypes,
31-
}
27+
pub mod message {
28+
use std::{convert::TryFrom, ops::Deref};
3229

33-
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
34-
pub struct HeartbeatValidatorMessage {
35-
pub from: ValidatorId,
36-
pub received: DateTime<Utc>,
37-
pub msg: MessageTypes,
30+
use crate::validator::messages::*;
31+
use serde::{Deserialize, Serialize};
32+
33+
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
34+
#[serde(try_from = "MessageTypes", into = "MessageTypes")]
35+
pub struct Message<T: Type>(T);
36+
37+
impl<T: Type> Message<T> {
38+
pub fn new(message: T) -> Self {
39+
Self(message)
40+
}
41+
42+
pub fn into_inner(self) -> T {
43+
self.0
44+
}
45+
}
46+
47+
impl<T: Type> Deref for Message<T> {
48+
type Target = T;
49+
50+
fn deref(&self) -> &Self::Target {
51+
&self.0
52+
}
53+
}
54+
55+
impl<T: Type> TryFrom<MessageTypes> for Message<T> {
56+
type Error = MessageTypeError<T>;
57+
58+
fn try_from(value: MessageTypes) -> Result<Self, Self::Error> {
59+
<T as TryFrom<MessageTypes>>::try_from(value).map(Self)
60+
}
61+
}
62+
63+
impl<T: Type> Into<MessageTypes> for Message<T> {
64+
fn into(self) -> MessageTypes {
65+
self.0.into()
66+
}
67+
}
68+
69+
#[cfg(test)]
70+
mod test {
71+
use super::*;
72+
use crate::sentry::MessageResponse;
73+
use chrono::{TimeZone, Utc};
74+
use serde_json::{from_value, json, to_value};
75+
76+
#[test]
77+
fn de_serialization_of_a_message() {
78+
let approve_state_message = json!({
79+
"from":"0x2892f6C41E0718eeeDd49D98D648C789668cA67d",
80+
"msg": {
81+
"type":"ApproveState",
82+
"stateRoot":"4739522efc1e81499541621759dadb331eaf08829d6a3851b4b654dfaddc9935",
83+
"signature":"0x00128a39b715e87475666c3220fc0400bf34a84d24f77571d2b4e1e88b141d52305438156e526ff4fe96b7a13e707ab2f6f3ca00bd928dabc7f516b56cfe6fd61c",
84+
"isHealthy":true,
85+
"exhausted":false
86+
},
87+
"received":"2021-01-05T14:00:48.549Z"
88+
});
89+
90+
let actual_message: MessageResponse<ApproveState> =
91+
from_value(approve_state_message.clone()).expect("Should deserialize");
92+
let expected_message = MessageResponse {
93+
from: "0x2892f6C41E0718eeeDd49D98D648C789668cA67d".parse().expect("Valid ValidatorId"),
94+
received: Utc.ymd(2021, 1, 5).and_hms_milli(14,0,48, 549),
95+
msg: Message::new(ApproveState {
96+
state_root: "4739522efc1e81499541621759dadb331eaf08829d6a3851b4b654dfaddc9935".to_string(),
97+
signature: "0x00128a39b715e87475666c3220fc0400bf34a84d24f77571d2b4e1e88b141d52305438156e526ff4fe96b7a13e707ab2f6f3ca00bd928dabc7f516b56cfe6fd61c".to_string(),
98+
is_healthy: true,
99+
exhausted: false,
100+
}),
101+
};
102+
103+
pretty_assertions::assert_eq!(expected_message, actual_message);
104+
pretty_assertions::assert_eq!(
105+
to_value(expected_message).expect("should serialize"),
106+
approve_state_message
107+
);
108+
}
109+
}
38110
}
39111

40112
#[serde(tag = "type", rename_all = "SCREAMING_SNAKE_CASE")]
@@ -119,7 +191,7 @@ pub struct LastApprovedResponse {
119191
/// None -> withHeartbeat=true wasn't passed
120192
/// Some(vec![]) (empty vec) or Some(heartbeats) - withHeartbeat=true was passed
121193
#[serde(default, skip_serializing_if = "Option::is_none")]
122-
pub heartbeats: Option<Vec<HeartbeatValidatorMessage>>,
194+
pub heartbeats: Option<Vec<MessageResponse<Heartbeat>>>,
123195
}
124196

125197
#[derive(Serialize, Deserialize, Debug)]
@@ -232,16 +304,16 @@ pub mod channel_list {
232304

233305
#[cfg(feature = "postgres")]
234306
mod postgres {
235-
use super::{
236-
ApproveStateValidatorMessage, HeartbeatValidatorMessage, NewStateValidatorMessage,
237-
ValidatorMessage,
307+
use super::{MessageResponse, ValidatorMessage};
308+
use crate::{
309+
sentry::EventAggregate,
310+
validator::{messages::Type as MessageType, MessageTypes},
238311
};
239-
use crate::sentry::EventAggregate;
240-
use crate::validator::MessageTypes;
241312
use bytes::BytesMut;
242313
use postgres_types::{accepts, to_sql_checked, IsNull, Json, ToSql, Type};
243-
use std::error::Error;
244-
use tokio_postgres::Row;
314+
use serde::Deserialize;
315+
use std::convert::TryFrom;
316+
use tokio_postgres::{Error, Row};
245317

246318
impl From<&Row> for EventAggregate {
247319
fn from(row: &Row) -> Self {
@@ -263,33 +335,20 @@ mod postgres {
263335
}
264336
}
265337

266-
impl From<&Row> for ApproveStateValidatorMessage {
267-
fn from(row: &Row) -> Self {
268-
Self {
269-
from: row.get("from"),
270-
received: row.get("received"),
271-
msg: row.get::<_, Json<MessageTypes>>("msg").0,
272-
}
273-
}
274-
}
275-
276-
impl From<&Row> for NewStateValidatorMessage {
277-
fn from(row: &Row) -> Self {
278-
Self {
279-
from: row.get("from"),
280-
received: row.get("received"),
281-
msg: row.get::<_, Json<MessageTypes>>("msg").0,
282-
}
283-
}
284-
}
338+
impl<T> TryFrom<&Row> for MessageResponse<T>
339+
where
340+
T: MessageType,
341+
for<'de> T: Deserialize<'de>,
342+
{
343+
type Error = Error;
285344

286-
impl From<&Row> for HeartbeatValidatorMessage {
287-
fn from(row: &Row) -> Self {
288-
Self {
345+
fn try_from(row: &Row) -> Result<Self, Self::Error> {
346+
Ok(Self {
289347
from: row.get("from"),
290348
received: row.get("received"),
291-
msg: row.get::<_, Json<MessageTypes>>("msg").0,
292-
}
349+
// guard against mistakes from wrong Queries
350+
msg: row.try_get::<_, Json<_>>("msg")?.0,
351+
})
293352
}
294353
}
295354

@@ -298,7 +357,7 @@ mod postgres {
298357
&self,
299358
ty: &Type,
300359
w: &mut BytesMut,
301-
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
360+
) -> Result<IsNull, Box<dyn std::error::Error + Sync + Send>> {
302361
Json(self).to_sql(ty, w)
303362
}
304363

0 commit comments

Comments
 (0)