11use std:: sync:: Arc ;
22
3- use anyhow:: { Context , anyhow } ;
3+ use anyhow:: Context ;
44use blake2:: { Blake2b , Digest , digest:: consts:: U64 } ;
5- use pallas_network:: miniprotocols:: localmsgsubmission:: DmqMsg ;
5+ use pallas_network:: miniprotocols:: localmsgsubmission:: { DmqMsg , DmqMsgPayload } ;
66
77use mithril_cardano_node_chain:: chain_observer:: ChainObserver ;
88use mithril_common:: {
99 StdResult ,
1010 crypto_helper:: { KesSigner , TryToBytes } ,
1111} ;
1212
13- use crate :: model:: DmqMessage ;
13+ use crate :: model:: { DmqMessage , SystemUnixTimestampProvider , UnixTimestampProvider } ;
1414
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 ;
1717
1818/// A builder for creating DMQ messages.
1919pub struct DmqMessageBuilder {
2020 kes_signer : Arc < dyn KesSigner > ,
2121 chain_observer : Arc < dyn ChainObserver > ,
22- ttl_blocks : u16 ,
22+ timestamp_provider : Arc < dyn UnixTimestampProvider > ,
23+ ttl_seconds : u16 ,
2324}
2425
2526impl DmqMessageBuilder {
@@ -28,43 +29,45 @@ impl DmqMessageBuilder {
2829 Self {
2930 kes_signer,
3031 chain_observer,
31- ttl_blocks : DMQ_MESSAGE_TTL_IN_BLOCKS ,
32+ timestamp_provider : Arc :: new ( SystemUnixTimestampProvider ) ,
33+ ttl_seconds : DMQ_MESSAGE_TTL_IN_SECONDS ,
3234 }
3335 }
3436
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;
3849
3950 self
4051 }
4152
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+
4265 /// Builds a DMQ message from the provided message bytes.
4366 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 )
6669 . try_into ( )
67- . with_context ( || "Failed to convert block number to u32 " ) ?;
70+ . with_context ( || "Failed to compute expires_at while building DMQ message " ) ?;
6871 let kes_period = self
6972 . chain_observer
7073 . get_current_kes_period ( )
@@ -75,16 +78,23 @@ impl DmqMessageBuilder {
7578 . kes_signer
7679 . sign ( message_bytes, kes_period)
7780 . 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+ } ,
8396 kes_signature : kes_signature. to_bytes_vec ( ) ?,
84- operational_certificate : operational_certificate. to_bytes_vec ( ) ?,
85- kes_period,
8697 } ;
87- dmq_message. msg_id = compute_msg_id ( & dmq_message) ;
8898
8999 Ok ( dmq_message. into ( ) )
90100 }
@@ -100,6 +110,8 @@ mod tests {
100110 test:: { crypto_helper:: KesSignerFake , double:: Dummy } ,
101111 } ;
102112
113+ use crate :: model:: MockUnixTimestampProvider ;
114+
103115 use super :: * ;
104116
105117 mod test_utils {
@@ -131,28 +143,39 @@ mod tests {
131143 } ,
132144 ..TimePoint :: dummy ( )
133145 } ) ) ) ;
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+ } ) ) ;
135156 let message = test_utils:: TestMessage {
136157 content : b"test" . to_vec ( ) ,
137158 } ;
138159
139160 let dmq_message = builder. build ( & message. to_bytes_vec ( ) . unwrap ( ) ) . await . unwrap ( ) ;
140161
141- assert ! ( !dmq_message. msg_id. is_empty( ) ) ;
162+ let DmqMsg {
163+ msg_payload,
164+ kes_signature : _,
165+ } = & * dmq_message;
142166 assert_eq ! (
143167 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+ } ,
148176 kes_signature: kes_signature. to_bytes_vec( ) . unwrap( ) ,
149- operational_certificate: operational_certificate. to_bytes_vec( ) . unwrap( ) ,
150- kes_period: 0 ,
151177 } ,
152- DmqMsg {
153- msg_id: vec![ ] ,
154- ..dmq_message. into( )
155- }
178+ dmq_message. into( )
156179 ) ;
157180 }
158181}
0 commit comments