1
- use crate :: chain_observer:: ChainAddress ;
2
- use crate :: crypto_helper:: key_decode_hex;
3
- use crate :: { chain_observer:: ChainObserver , entities:: Epoch } ;
1
+ use crate :: {
2
+ chain_observer:: { ChainAddress , ChainObserver } ,
3
+ crypto_helper:: {
4
+ key_decode_hex, EraMarkersSigner , EraMarkersVerifier , EraMarkersVerifierSignature ,
5
+ EraMarkersVerifierVerificationKey ,
6
+ } ,
7
+ entities:: Epoch ,
8
+ } ;
4
9
use async_trait:: async_trait;
10
+ use hex:: { FromHex , ToHex } ;
5
11
use serde:: { Deserialize , Serialize } ;
6
12
use std:: error:: Error as StdError ;
7
13
use std:: sync:: Arc ;
8
14
use thiserror:: Error ;
9
15
16
+ type GeneralError = Box < dyn StdError + Sync + Send > ;
17
+
10
18
// TODO: remove EraMarker & EraReaderAdapter w/ they are available
11
19
12
20
/// Value object that represents a tag of Era change.
@@ -31,38 +39,101 @@ impl EraMarker {
31
39
#[ async_trait]
32
40
pub trait EraReaderAdapter : Sync + Send {
33
41
/// Read era markers from the underlying adapter.
34
- async fn read ( & self ) -> Result < Vec < EraMarker > , Box < dyn StdError + Sync + Send > > ;
42
+ async fn read ( & self ) -> Result < Vec < EraMarker > , GeneralError > ;
35
43
}
36
44
37
45
// TODO: Keep Cardano Chain Adapter part below
38
46
39
47
type HexEncodeEraMarkerSignature = String ;
40
48
49
+ /// [EraMarkersPayload] related errors.
50
+ #[ derive( Debug , Error ) ]
51
+ pub enum EraMarkersPayloadError {
52
+ /// Error raised when the message serialization fails
53
+ #[ error( "could not serialize message: {0}" ) ]
54
+ SerializeMessage ( GeneralError ) ,
55
+
56
+ /// Error raised when the signature deserialization fails
57
+ #[ error( "could not deserialize signature: {0}" ) ]
58
+ DeserializeSignature ( GeneralError ) ,
59
+
60
+ /// Error raised when the signature is invalid
61
+ #[ error( "could not verify signature: {0}" ) ]
62
+ VerifySignature ( GeneralError ) ,
63
+
64
+ /// Error raised when the signing the markers
65
+ #[ error( "could not create signature: {0}" ) ]
66
+ CreateSignature ( GeneralError ) ,
67
+ }
68
+
41
69
#[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
42
70
struct EraMarkersPayload {
43
71
markers : Vec < EraMarker > ,
44
72
signature : HexEncodeEraMarkerSignature ,
45
73
}
46
74
75
+ impl EraMarkersPayload {
76
+ fn message_to_sign ( & self ) -> Result < Vec < u8 > , EraMarkersPayloadError > {
77
+ serde_json:: to_vec ( & self . markers )
78
+ . map_err ( |e| EraMarkersPayloadError :: SerializeMessage ( e. into ( ) ) )
79
+ }
80
+
81
+ fn verify_signature (
82
+ & self ,
83
+ verification_key : EraMarkersVerifierVerificationKey ,
84
+ ) -> Result < ( ) , EraMarkersPayloadError > {
85
+ let signature = EraMarkersVerifierSignature :: from_bytes (
86
+ & Vec :: from_hex ( & self . signature )
87
+ . map_err ( |e| EraMarkersPayloadError :: DeserializeSignature ( e. into ( ) ) ) ?,
88
+ )
89
+ . map_err ( |e| EraMarkersPayloadError :: DeserializeSignature ( e. into ( ) ) ) ?;
90
+ let markers_verifier = EraMarkersVerifier :: from_verification_key ( verification_key) ;
91
+ markers_verifier
92
+ . verify ( & self . message_to_sign ( ) ?, & signature)
93
+ . map_err ( |e| EraMarkersPayloadError :: VerifySignature ( e. into ( ) ) )
94
+ }
95
+
96
+ #[ cfg( any( test, feature = "test_only" ) ) ]
97
+ fn sign ( self , signer : & EraMarkersSigner ) -> Result < Self , EraMarkersPayloadError > {
98
+ let signature = signer
99
+ . sign (
100
+ & self
101
+ . message_to_sign ( )
102
+ . map_err ( |e| EraMarkersPayloadError :: CreateSignature ( e. into ( ) ) ) ?,
103
+ )
104
+ . encode_hex :: < String > ( ) ;
105
+ Ok ( Self {
106
+ markers : self . markers ,
107
+ signature,
108
+ } )
109
+ }
110
+ }
111
+
47
112
/// Cardano Chain adapter retrieves era markers on chain
48
113
pub struct CardanoChainAdapter {
49
114
address : ChainAddress ,
50
115
chain_observer : Arc < dyn ChainObserver > ,
116
+ verification_key : EraMarkersVerifierVerificationKey ,
51
117
}
52
118
53
119
impl CardanoChainAdapter {
54
120
/// CardanoChainAdapter factory
55
- pub fn new ( address : ChainAddress , chain_observer : Arc < dyn ChainObserver > ) -> Self {
121
+ pub fn new (
122
+ address : ChainAddress ,
123
+ chain_observer : Arc < dyn ChainObserver > ,
124
+ verification_key : EraMarkersVerifierVerificationKey ,
125
+ ) -> Self {
56
126
Self {
57
127
address,
58
128
chain_observer,
129
+ verification_key,
59
130
}
60
131
}
61
132
}
62
133
63
134
#[ async_trait]
64
135
impl EraReaderAdapter for CardanoChainAdapter {
65
- async fn read ( & self ) -> Result < Vec < EraMarker > , Box < dyn StdError + Sync + Send > > {
136
+ async fn read ( & self ) -> Result < Vec < EraMarker > , GeneralError > {
66
137
let tx_datums = self
67
138
. chain_observer
68
139
. get_current_datums ( & self . address )
@@ -72,7 +143,12 @@ impl EraReaderAdapter for CardanoChainAdapter {
72
143
. filter_map ( |datum| datum. get_field_raw_value ( "bytes" , 0 ) . ok ( ) )
73
144
. filter_map ( |field_value| field_value. as_str ( ) . map ( |s| s. to_string ( ) ) )
74
145
. filter_map ( |field_value_str| key_decode_hex ( & field_value_str) . ok ( ) )
75
- . map ( |era_markers_payload : EraMarkersPayload | era_markers_payload. markers )
146
+ . filter_map ( |era_markers_payload : EraMarkersPayload | {
147
+ era_markers_payload
148
+ . verify_signature ( self . verification_key )
149
+ . ok ( )
150
+ . map ( |_| era_markers_payload. markers )
151
+ } )
76
152
. collect :: < Vec < Vec < EraMarker > > > ( ) ;
77
153
Ok ( markers_list. first ( ) . unwrap_or ( & Vec :: new ( ) ) . to_owned ( ) )
78
154
}
@@ -81,7 +157,7 @@ impl EraReaderAdapter for CardanoChainAdapter {
81
157
#[ cfg( test) ]
82
158
mod test {
83
159
use crate :: chain_observer:: { FakeObserver , TxDatum } ;
84
- use crate :: crypto_helper:: key_encode_hex;
160
+ use crate :: crypto_helper:: { key_encode_hex, EraMarkersSigner } ;
85
161
86
162
use super :: * ;
87
163
@@ -99,35 +175,42 @@ mod test {
99
175
100
176
#[ tokio:: test]
101
177
async fn test_cardano_chain_adapter ( ) {
178
+ let era_markers_signer = EraMarkersSigner :: create_deterministic_signer ( ) ;
102
179
let fake_address = "addr_test_123456" . to_string ( ) ;
103
180
let era_marker_payload_1 = EraMarkersPayload {
104
181
markers : vec ! [
105
182
EraMarker :: new( "thales" , Some ( Epoch ( 1 ) ) ) ,
106
- EraMarker :: new( "pythagors " , None ) ,
183
+ EraMarker :: new( "pythagoras " , None ) ,
107
184
] ,
108
185
signature : "" . to_string ( ) ,
109
186
} ;
110
187
let era_marker_payload_2 = EraMarkersPayload {
111
188
markers : vec ! [
112
189
EraMarker :: new( "thales" , Some ( Epoch ( 1 ) ) ) ,
113
- EraMarker :: new( "pythagors " , Some ( Epoch ( 2 ) ) ) ,
190
+ EraMarker :: new( "pythagoras " , Some ( Epoch ( 2 ) ) ) ,
114
191
] ,
115
192
signature : "" . to_string ( ) ,
116
193
} ;
117
194
let mut fake_datums = dummy_tx_datums_from_markers_payload ( vec ! [
118
- era_marker_payload_1. clone( ) ,
119
- era_marker_payload_2,
195
+ era_marker_payload_1,
196
+ era_marker_payload_2
197
+ . clone( )
198
+ . sign( & era_markers_signer)
199
+ . unwrap( ) ,
120
200
] ) ;
121
201
fake_datums. push ( TxDatum ( "not_valid_datum" . to_string ( ) ) ) ;
122
202
let chain_observer = FakeObserver :: default ( ) ;
123
203
chain_observer. set_datums ( fake_datums. clone ( ) ) . await ;
124
- let cardano_chain_adapter =
125
- CardanoChainAdapter :: new ( fake_address, Arc :: new ( chain_observer) ) ;
204
+ let cardano_chain_adapter = CardanoChainAdapter :: new (
205
+ fake_address,
206
+ Arc :: new ( chain_observer) ,
207
+ era_markers_signer. create_verifier ( ) . to_verification_key ( ) ,
208
+ ) ;
126
209
let markers = cardano_chain_adapter
127
210
. read ( )
128
211
. await
129
212
. expect ( "CardanoChainAdapter read should not fail" ) ;
130
- let expected_markers = era_marker_payload_1 . markers . to_owned ( ) ;
213
+ let expected_markers = era_marker_payload_2 . markers . to_owned ( ) ;
131
214
assert_eq ! ( expected_markers, markers) ;
132
215
}
133
216
}
0 commit comments