1
1
use std:: sync:: Arc ;
2
2
3
- use anyhow:: { Context , anyhow } ;
3
+ use anyhow:: Context ;
4
4
use blake2:: { Blake2b , Digest , digest:: consts:: U64 } ;
5
- use pallas_network:: miniprotocols:: localmsgsubmission:: DmqMsg ;
5
+ use pallas_network:: miniprotocols:: localmsgsubmission:: { DmqMsg , DmqMsgPayload } ;
6
6
7
7
use mithril_cardano_node_chain:: chain_observer:: ChainObserver ;
8
8
use mithril_common:: {
9
9
StdResult ,
10
10
crypto_helper:: { KesSigner , TryToBytes } ,
11
11
} ;
12
12
13
- use crate :: model:: DmqMessage ;
13
+ use crate :: model:: { DmqMessage , SystemUnixTimestampProvider , UnixTimestampProvider } ;
14
14
15
- /// The TTL (Time To Live) for DMQ messages in blocks .
16
- const DMQ_MESSAGE_TTL_IN_BLOCKS : u16 = 100 ;
15
+ /// The TTL (Time To Live) for DMQ messages in seconds (default is 30 minutes) .
16
+ const DMQ_MESSAGE_TTL_IN_SECONDS : u16 = 1800 ;
17
17
18
18
/// A builder for creating DMQ messages.
19
19
pub struct DmqMessageBuilder {
20
20
kes_signer : Arc < dyn KesSigner > ,
21
21
chain_observer : Arc < dyn ChainObserver > ,
22
- ttl_blocks : u16 ,
22
+ timestamp_provider : Arc < dyn UnixTimestampProvider > ,
23
+ ttl_seconds : u16 ,
23
24
}
24
25
25
26
impl DmqMessageBuilder {
@@ -28,43 +29,45 @@ impl DmqMessageBuilder {
28
29
Self {
29
30
kes_signer,
30
31
chain_observer,
31
- ttl_blocks : DMQ_MESSAGE_TTL_IN_BLOCKS ,
32
+ timestamp_provider : Arc :: new ( SystemUnixTimestampProvider ) ,
33
+ ttl_seconds : DMQ_MESSAGE_TTL_IN_SECONDS ,
32
34
}
33
35
}
34
36
35
- /// Set the TTL (Time To Live) for DMQ messages in blocks.
36
- pub fn set_ttl ( mut self , ttl_blocks : u16 ) -> Self {
37
- self . ttl_blocks = ttl_blocks;
37
+ /// Sets the timestamp provider for the DMQ message builder.
38
+ pub fn set_timestamp_provider (
39
+ mut self ,
40
+ timestamp_provider : Arc < dyn UnixTimestampProvider > ,
41
+ ) -> Self {
42
+ self . timestamp_provider = timestamp_provider;
43
+ self
44
+ }
45
+
46
+ /// Sets the TTL (Time To Live) for DMQ messages in seconds.
47
+ pub fn set_ttl ( mut self , ttl_seconds : u16 ) -> Self {
48
+ self . ttl_seconds = ttl_seconds;
38
49
39
50
self
40
51
}
41
52
53
+ /// Computes a message id for a DMQ message payload.
54
+ fn compute_msg_id ( dmq_message_payload : & DmqMsgPayload ) -> Vec < u8 > {
55
+ let mut hasher = Blake2b :: < U64 > :: new ( ) ;
56
+ hasher. update ( & dmq_message_payload. msg_body ) ;
57
+ hasher. update ( dmq_message_payload. kes_period . to_be_bytes ( ) ) ;
58
+ hasher. update ( & dmq_message_payload. operational_certificate ) ;
59
+ hasher. update ( & dmq_message_payload. cold_verification_key ) ;
60
+ hasher. update ( dmq_message_payload. expires_at . to_be_bytes ( ) ) ;
61
+
62
+ hasher. finalize ( ) . to_vec ( )
63
+ }
64
+
42
65
/// Builds a DMQ message from the provided message bytes.
43
66
pub async fn build ( & self , message_bytes : & [ u8 ] ) -> StdResult < DmqMessage > {
44
- fn compute_msg_id ( dmq_message : & DmqMsg ) -> Vec < u8 > {
45
- let mut hasher = Blake2b :: < U64 > :: new ( ) ;
46
- hasher. update ( & dmq_message. msg_body ) ;
47
- hasher. update ( dmq_message. block_number . to_be_bytes ( ) ) ;
48
- hasher. update ( dmq_message. ttl . to_be_bytes ( ) ) ;
49
- hasher. update ( & dmq_message. kes_signature ) ;
50
- hasher. update ( & dmq_message. operational_certificate ) ;
51
- hasher. update ( dmq_message. kes_period . to_be_bytes ( ) ) ;
52
-
53
- hasher. finalize ( ) . to_vec ( )
54
- }
55
-
56
- let block_number = self
57
- . chain_observer
58
- . get_current_chain_point ( )
59
- . await
60
- . with_context ( || "Failed to get current chain point while building DMQ message" ) ?
61
- . ok_or ( anyhow ! (
62
- "No current chain point available while building DMQ message"
63
- ) ) ?
64
- . block_number ;
65
- let block_number = ( * block_number)
67
+ let expires_at: u32 = ( self . timestamp_provider . current_timestamp ( ) ?
68
+ + self . ttl_seconds as u64 )
66
69
. try_into ( )
67
- . with_context ( || "Failed to convert block number to u32 " ) ?;
70
+ . with_context ( || "Failed to compute expires_at while building DMQ message " ) ?;
68
71
let kes_period = self
69
72
. chain_observer
70
73
. get_current_kes_period ( )
@@ -75,16 +78,23 @@ impl DmqMessageBuilder {
75
78
. kes_signer
76
79
. sign ( message_bytes, kes_period)
77
80
. with_context ( || "Failed to KES sign message while building DMQ message" ) ?;
78
- let mut dmq_message = DmqMsg {
79
- msg_id : vec ! [ ] ,
80
- msg_body : message_bytes. to_vec ( ) ,
81
- block_number,
82
- ttl : self . ttl_blocks ,
81
+
82
+ let dmq_message = DmqMsg {
83
+ msg_payload : {
84
+ let mut dmq_message_payload = DmqMsgPayload {
85
+ msg_id : vec ! [ ] ,
86
+ msg_body : message_bytes. to_vec ( ) ,
87
+ kes_period : kes_period as u64 ,
88
+ operational_certificate : operational_certificate. to_bytes_vec ( ) ?, // TODO: remove the cold verification key in the op cert
89
+ cold_verification_key : vec ! [ ] ,
90
+ expires_at,
91
+ } ;
92
+ dmq_message_payload. msg_id = Self :: compute_msg_id ( & dmq_message_payload) ;
93
+
94
+ dmq_message_payload
95
+ } ,
83
96
kes_signature : kes_signature. to_bytes_vec ( ) ?,
84
- operational_certificate : operational_certificate. to_bytes_vec ( ) ?,
85
- kes_period,
86
97
} ;
87
- dmq_message. msg_id = compute_msg_id ( & dmq_message) ;
88
98
89
99
Ok ( dmq_message. into ( ) )
90
100
}
@@ -100,6 +110,8 @@ mod tests {
100
110
test:: { crypto_helper:: KesSignerFake , double:: Dummy } ,
101
111
} ;
102
112
113
+ use crate :: model:: MockUnixTimestampProvider ;
114
+
103
115
use super :: * ;
104
116
105
117
mod test_utils {
@@ -131,28 +143,39 @@ mod tests {
131
143
} ,
132
144
..TimePoint :: dummy ( )
133
145
} ) ) ) ;
134
- let builder = DmqMessageBuilder :: new ( kes_signer, chain_observer) . set_ttl ( 100 ) ;
146
+ let builder = DmqMessageBuilder :: new ( kes_signer, chain_observer)
147
+ . set_ttl ( 1000 )
148
+ . set_timestamp_provider ( Arc :: new ( {
149
+ let mut mock_timestamp_provider = MockUnixTimestampProvider :: new ( ) ;
150
+ mock_timestamp_provider
151
+ . expect_current_timestamp ( )
152
+ . returning ( || Ok ( 234 ) ) ;
153
+
154
+ mock_timestamp_provider
155
+ } ) ) ;
135
156
let message = test_utils:: TestMessage {
136
157
content : b"test" . to_vec ( ) ,
137
158
} ;
138
159
139
160
let dmq_message = builder. build ( & message. to_bytes_vec ( ) . unwrap ( ) ) . await . unwrap ( ) ;
140
161
141
- assert ! ( !dmq_message. msg_id. is_empty( ) ) ;
162
+ let DmqMsg {
163
+ msg_payload,
164
+ kes_signature : _,
165
+ } = & * dmq_message;
142
166
assert_eq ! (
143
167
DmqMsg {
144
- msg_id: vec![ ] ,
145
- msg_body: b"test" . to_vec( ) ,
146
- block_number: 123 ,
147
- ttl: 100 ,
168
+ msg_payload: DmqMsgPayload {
169
+ msg_id: DmqMessageBuilder :: compute_msg_id( msg_payload) ,
170
+ msg_body: b"test" . to_vec( ) ,
171
+ kes_period: 0 ,
172
+ operational_certificate: operational_certificate. to_bytes_vec( ) . unwrap( ) ,
173
+ cold_verification_key: vec![ ] , // TODO: fix
174
+ expires_at: 1234 ,
175
+ } ,
148
176
kes_signature: kes_signature. to_bytes_vec( ) . unwrap( ) ,
149
- operational_certificate: operational_certificate. to_bytes_vec( ) . unwrap( ) ,
150
- kes_period: 0 ,
151
177
} ,
152
- DmqMsg {
153
- msg_id: vec![ ] ,
154
- ..dmq_message. into( )
155
- }
178
+ dmq_message. into( )
156
179
) ;
157
180
}
158
181
}
0 commit comments