8
8
clippy:: arithmetic_side_effects
9
9
) ]
10
10
11
- use std:: { fmt:: Debug , fs:: File , io:: BufReader , ops:: Deref , path:: Path } ;
11
+ use std:: {
12
+ fmt:: Debug ,
13
+ fs:: { self , File } ,
14
+ io:: BufReader ,
15
+ ops:: Deref ,
16
+ path:: { Path , PathBuf } ,
17
+ } ;
12
18
13
- use derive_more:: Deref ;
14
- use eyre:: { bail, eyre, Result , WrapErr } ;
19
+ use derive_more:: { Deref , From } ;
20
+ use eyre:: { bail, eyre, ErrReport , Result , WrapErr } ;
15
21
use iroha_config:: genesis:: Configuration ;
16
22
use iroha_crypto:: { KeyPair , PublicKey } ;
17
- #[ cfg( not( test) ) ]
18
- use iroha_data_model:: validator:: Validator ;
19
23
use iroha_data_model:: {
20
24
asset:: AssetDefinition ,
21
25
prelude:: { Metadata , * } ,
26
+ validator:: Validator ,
22
27
} ;
23
28
use iroha_primitives:: small:: { smallvec, SmallVec } ;
24
29
use iroha_schema:: IntoSchema ;
25
30
use serde:: { Deserialize , Serialize } ;
26
- #[ cfg( test) ]
27
- use MockValidator as Validator ;
28
31
29
32
/// Time to live for genesis transactions.
30
33
const GENESIS_TRANSACTIONS_TTL_MS : u64 = 100_000 ;
@@ -77,7 +80,10 @@ impl GenesisNetworkTrait for GenesisNetwork {
77
80
let transactions_iter = raw_block. transactions . into_iter ( ) ;
78
81
#[ cfg( not( test) ) ]
79
82
let transactions_iter = transactions_iter. chain ( std:: iter:: once ( GenesisTransaction {
80
- isi : SmallVec ( smallvec ! [ UpgradeBox :: new( raw_block. validator) . into( ) ] ) ,
83
+ isi : SmallVec ( smallvec ! [ UpgradeBox :: new( Validator :: try_from(
84
+ raw_block. validator
85
+ ) ?)
86
+ . into( ) ] ) ,
81
87
} ) ) ;
82
88
83
89
let transactions = transactions_iter
@@ -100,21 +106,93 @@ impl GenesisNetworkTrait for GenesisNetwork {
100
106
}
101
107
}
102
108
103
- /// Mock of [`Validator`](iroha_data_model::validator::Validator) for unit tests
104
- ///
105
- /// Aliased to `Validator` when `cfg(test)`.
106
- #[ cfg( test) ]
107
- #[ derive( Debug , Clone , Copy , Deserialize , Serialize , IntoSchema ) ]
108
- #[ repr( transparent) ]
109
- pub struct MockValidator ;
110
-
111
109
/// [`RawGenesisBlock`] is an initial block of the network
112
110
#[ derive( Debug , Clone , Deserialize , Serialize , IntoSchema ) ]
113
111
pub struct RawGenesisBlock {
114
112
/// Transactions
115
113
pub transactions : SmallVec < [ GenesisTransaction ; 2 ] > ,
116
114
/// Runtime Validator
117
- pub validator : Validator ,
115
+ pub validator : ValidatorMode ,
116
+ }
117
+
118
+ /// Ways to provide validator either directly as base64 encoded string or as path to wasm file
119
+ #[ derive( Debug , Clone , Serialize , Deserialize , IntoSchema , From ) ]
120
+ #[ serde( untagged) ]
121
+ pub enum ValidatorMode {
122
+ /// Path to validator wasm file
123
+ // In the first place to initially try to parse path
124
+ Path ( ValidatorPath ) ,
125
+ /// Validator encoded as base64 string
126
+ Inline ( Validator ) ,
127
+ }
128
+
129
+ impl ValidatorMode {
130
+ fn set_genesis_path ( & mut self , genesis_path : impl AsRef < Path > ) {
131
+ if let Self :: Path ( path) = self {
132
+ path. set_genesis_path ( genesis_path) ;
133
+ }
134
+ }
135
+ }
136
+
137
+ impl TryFrom < ValidatorMode > for Validator {
138
+ type Error = ErrReport ;
139
+
140
+ fn try_from ( value : ValidatorMode ) -> Result < Self > {
141
+ match value {
142
+ ValidatorMode :: Inline ( validator) => Ok ( validator) ,
143
+ ValidatorMode :: Path ( ValidatorPath {
144
+ validator_path : relative_validator_path,
145
+ } ) => {
146
+ let wasm = fs:: read ( & relative_validator_path)
147
+ . wrap_err ( format ! ( "Failed to open {:?}" , & relative_validator_path) ) ?;
148
+ Ok ( Validator :: new ( WasmSmartContract :: from_compiled ( wasm) ) )
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ /// Path to the validator relative to genesis location
155
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
156
+ pub struct ValidatorPath {
157
+ /// Path to validator.
158
+ /// If path is absolute it will be used directly otherwise it will be treated as relative to genesis location.
159
+ pub validator_path : PathBuf ,
160
+ }
161
+
162
+ // Manual implementation because we want `PathBuf` appear as `String` in schema
163
+ impl iroha_schema:: TypeId for ValidatorPath {
164
+ fn id ( ) -> String {
165
+ "ValidatorPath" . to_string ( )
166
+ }
167
+ }
168
+ impl iroha_schema:: IntoSchema for ValidatorPath {
169
+ fn type_name ( ) -> String {
170
+ "ValidatorPath" . to_string ( )
171
+ }
172
+ fn update_schema_map ( map : & mut iroha_schema:: MetaMap ) {
173
+ if !map. contains_key :: < Self > ( ) {
174
+ map. insert :: < Self > ( iroha_schema:: Metadata :: Struct (
175
+ iroha_schema:: NamedFieldsMeta {
176
+ declarations : vec ! [ iroha_schema:: Declaration {
177
+ name: String :: from( stringify!( validator_relative_path) ) ,
178
+ ty: core:: any:: TypeId :: of:: <String >( ) ,
179
+ } ] ,
180
+ } ,
181
+ ) ) ;
182
+ <String as iroha_schema:: IntoSchema >:: update_schema_map ( map) ;
183
+ }
184
+ }
185
+ }
186
+
187
+ impl ValidatorPath {
188
+ fn set_genesis_path ( & mut self , genesis_path : impl AsRef < Path > ) {
189
+ let path_to_validator = genesis_path
190
+ . as_ref ( )
191
+ . parent ( )
192
+ . expect ( "Genesis must be in some directory" )
193
+ . join ( & self . validator_path ) ;
194
+ self . validator_path = path_to_validator;
195
+ }
118
196
}
119
197
120
198
impl RawGenesisBlock {
@@ -135,10 +213,12 @@ impl RawGenesisBlock {
135
213
iroha_logger:: warn!( %size, threshold = %Self :: WARN_ON_GENESIS_GTE , "Genesis is quite large, it will take some time to apply it" ) ;
136
214
}
137
215
let reader = BufReader :: new ( file) ;
138
- serde_json:: from_reader ( reader) . wrap_err ( format ! (
216
+ let mut raw_genesis_block : Self = serde_json:: from_reader ( reader) . wrap_err ( format ! (
139
217
"Failed to deserialize raw genesis block from {:?}" ,
140
218
& path
141
- ) )
219
+ ) ) ?;
220
+ raw_genesis_block. validator . set_genesis_path ( path) ;
221
+ Ok ( raw_genesis_block)
142
222
}
143
223
}
144
224
@@ -192,10 +272,10 @@ pub struct RawGenesisDomainBuilder<S> {
192
272
}
193
273
194
274
mod validator_state {
195
- use super :: Validator ;
275
+ use super :: ValidatorMode ;
196
276
197
- #[ cfg_attr( test, derive( Clone , Copy ) ) ]
198
- pub struct Set ( pub Validator ) ;
277
+ #[ cfg_attr( test, derive( Clone ) ) ]
278
+ pub struct Set ( pub ValidatorMode ) ;
199
279
200
280
#[ derive( Clone , Copy ) ]
201
281
pub struct Unset ;
@@ -217,10 +297,13 @@ impl RawGenesisBlockBuilder<validator_state::Unset> {
217
297
}
218
298
219
299
/// Set the validator.
220
- pub fn validator ( self , validator : Validator ) -> RawGenesisBlockBuilder < validator_state:: Set > {
300
+ pub fn validator (
301
+ self ,
302
+ validator : impl Into < ValidatorMode > ,
303
+ ) -> RawGenesisBlockBuilder < validator_state:: Set > {
221
304
RawGenesisBlockBuilder {
222
305
transaction : self . transaction ,
223
- state : validator_state:: Set ( validator) ,
306
+ state : validator_state:: Set ( validator. into ( ) ) ,
224
307
}
225
308
}
226
309
}
@@ -323,6 +406,12 @@ mod tests {
323
406
324
407
use super :: * ;
325
408
409
+ fn dummy_validator ( ) -> ValidatorMode {
410
+ ValidatorMode :: Path ( ValidatorPath {
411
+ validator_path : "./validator.wasm" . into ( ) ,
412
+ } )
413
+ }
414
+
326
415
#[ test]
327
416
#[ allow( clippy:: expect_used) ]
328
417
fn load_new_genesis_block ( ) -> Result < ( ) > {
@@ -338,7 +427,7 @@ mod tests {
338
427
. domain ( "wonderland" . parse ( ) ?)
339
428
. account ( "alice" . parse ( ) ?, alice_public_key)
340
429
. finish_domain ( )
341
- . validator ( MockValidator )
430
+ . validator ( dummy_validator ( ) )
342
431
. build ( ) ,
343
432
Some (
344
433
& ConfigurationProxy {
@@ -373,7 +462,7 @@ mod tests {
373
462
. finish_domain ( ) ;
374
463
375
464
// In real cases validator should be constructed from a wasm blob
376
- let finished_genesis_block = genesis_builder. validator ( MockValidator ) . build ( ) ;
465
+ let finished_genesis_block = genesis_builder. validator ( dummy_validator ( ) ) . build ( ) ;
377
466
{
378
467
let domain_id: DomainId = "wonderland" . parse ( ) . unwrap ( ) ;
379
468
assert_eq ! (
0 commit comments