1
- use std:: cell:: RefCell ;
2
1
use std:: collections:: BTreeSet ;
3
2
use std:: collections:: HashSet ;
4
- use std:: iter:: empty;
5
- use std:: rc:: Rc ;
6
- use std:: sync:: Mutex ;
7
3
8
4
use wasmer:: wasmparser:: Import ;
9
5
use wasmer:: wasmparser:: TypeRef ;
@@ -101,38 +97,42 @@ const MAX_TOTAL_FUNCTION_PARAMS: usize = 10_000;
101
97
/// during static validation.
102
98
const MAX_FUNCTION_RESULTS : usize = 1 ;
103
99
104
- #[ derive( Clone ) ]
105
- pub enum Logs {
106
- On ( RefCell < Vec < String > > ) ,
100
+ #[ derive( Clone , Copy ) ]
101
+ pub enum LogOutput {
102
+ StdOut ,
103
+ StdErr ,
104
+ }
105
+ #[ derive( Clone , Copy , Default ) ]
106
+ pub enum Logger < ' a > {
107
+ On {
108
+ prefix : & ' a str ,
109
+ output : LogOutput ,
110
+ } ,
111
+ #[ default]
107
112
Off ,
108
113
}
109
114
110
- impl Logs {
111
- pub fn new ( ) -> Self {
112
- On ( RefCell :: new ( Vec :: new ( ) ) )
115
+ impl < ' a > Logger < ' a > {
116
+ pub fn with_config ( output : LogOutput , prefix : & ' a str ) -> Self {
117
+ On { output , prefix }
113
118
}
114
119
115
- // Gets access to logs for writing
116
- pub fn open ( & mut self ) -> Option < & mut Vec < String > > {
117
- match self {
118
- On ( data) => {
119
- let mut data = data. borrow_mut ( ) ;
120
- Some ( data. as_mut ( ) )
120
+ /// Adds a message to the logs, if they are enabled.
121
+ /// This is a convenience method for adding a single message.
122
+ ///
123
+ /// Takes a closure that returns the message to add to avoid unnecessary allocations.
124
+ pub fn add ( & self , msg_fn : impl FnOnce ( ) -> String ) {
125
+ if let On { prefix, output } = & self {
126
+ let msg = msg_fn ( ) ;
127
+ match output {
128
+ LogOutput :: StdOut => println ! ( "{prefix}{msg}" ) ,
129
+ LogOutput :: StdErr => eprintln ! ( "{prefix}{msg}" ) ,
121
130
}
122
- Off => None ,
123
131
}
124
132
}
125
-
126
- pub fn iter ( & self ) -> impl Iterator < Item = String > {
127
- let iter = match self {
128
- On ( data) => data. borrow ( ) . iter ( ) ,
129
- Off => Vec :: new ( ) . into_iter ( ) . into ( ) , // How to create am empty Iter<String> ?!?!?!?
130
- } ;
131
- iter
132
- }
133
133
}
134
134
135
- use Logs :: * ;
135
+ use Logger :: * ;
136
136
137
137
/// Checks if the data is valid wasm and compatibility with the CosmWasm API (imports and exports)
138
138
pub fn check_wasm ( wasm_code : & [ u8 ] , available_capabilities : & HashSet < String > ) -> VmResult < ( ) > {
@@ -142,21 +142,19 @@ pub fn check_wasm(wasm_code: &[u8], available_capabilities: &HashSet<String>) ->
142
142
pub fn check_wasm_with_logs (
143
143
wasm_code : & [ u8 ] ,
144
144
available_capabilities : & HashSet < String > ,
145
- logs : Logs ,
145
+ logs : Logger < ' _ > ,
146
146
) -> VmResult < ( ) > {
147
- if let Some ( logs) = logs. clone ( ) . open ( ) {
148
- logs. push ( format ! ( "Size of Wasm blob: {}" , wasm_code. len( ) ) ) ;
149
- }
147
+ logs. add ( || format ! ( "Size of Wasm blob: {}" , wasm_code. len( ) ) ) ;
150
148
151
149
let mut module = ParsedWasm :: parse ( wasm_code) ?;
152
150
153
151
check_wasm_tables ( & module) ?;
154
152
check_wasm_memories ( & module) ?;
155
153
check_interface_version ( & module) ?;
156
- check_wasm_exports ( & module, logs. clone ( ) ) ?;
157
- check_wasm_imports ( & module, SUPPORTED_IMPORTS , logs. clone ( ) ) ?;
158
- check_wasm_capabilities ( & module, available_capabilities, logs. clone ( ) ) ?;
159
- check_wasm_functions ( & module, logs. clone ( ) ) ?;
154
+ check_wasm_exports ( & module, logs) ?;
155
+ check_wasm_imports ( & module, SUPPORTED_IMPORTS , logs) ?;
156
+ check_wasm_capabilities ( & module, available_capabilities, logs) ?;
157
+ check_wasm_functions ( & module, logs) ?;
160
158
161
159
module. validate_funcs ( )
162
160
}
@@ -237,15 +235,10 @@ fn check_interface_version(module: &ParsedWasm) -> VmResult<()> {
237
235
}
238
236
}
239
237
240
- fn check_wasm_exports ( module : & ParsedWasm , mut logs : Logs ) -> VmResult < ( ) > {
238
+ fn check_wasm_exports ( module : & ParsedWasm , logs : Logger ) -> VmResult < ( ) > {
241
239
let available_exports: HashSet < String > = module. exported_function_names ( None ) ;
242
240
243
- if let Some ( logs) = logs. open ( ) {
244
- logs. push ( format ! (
245
- "Exports: {}" ,
246
- available_exports. to_string_limited( 20_000 )
247
- ) ) ;
248
- }
241
+ logs. add ( || format ! ( "Exports: {}" , available_exports. to_string_limited( 20_000 ) ) ) ;
249
242
250
243
for required_export in REQUIRED_EXPORTS {
251
244
if !available_exports. contains ( * required_export) {
@@ -263,10 +256,10 @@ fn check_wasm_exports(module: &ParsedWasm, mut logs: Logs) -> VmResult<()> {
263
256
fn check_wasm_imports (
264
257
module : & ParsedWasm ,
265
258
supported_imports : & [ & str ] ,
266
- mut logs : Logs ,
259
+ logs : Logger ,
267
260
) -> VmResult < ( ) > {
268
- if let Some ( logs) = logs . open ( ) {
269
- logs . push ( format ! (
261
+ logs. add ( || {
262
+ format ! (
270
263
"Imports ({}): {}" ,
271
264
module. imports. len( ) ,
272
265
module
@@ -275,8 +268,8 @@ fn check_wasm_imports(
275
268
. map( |import| full_import_name( import) )
276
269
. collect:: <Vec <_>>( )
277
270
. join( ", " )
278
- ) ) ;
279
- }
271
+ )
272
+ } ) ;
280
273
281
274
if module. imports . len ( ) > MAX_IMPORTS {
282
275
return Err ( VmError :: static_validation_err ( format ! (
@@ -314,15 +307,15 @@ fn full_import_name(ie: &Import) -> String {
314
307
fn check_wasm_capabilities (
315
308
module : & ParsedWasm ,
316
309
available_capabilities : & HashSet < String > ,
317
- mut logs : Logs ,
310
+ logs : Logger ,
318
311
) -> VmResult < ( ) > {
319
312
let required_capabilities = required_capabilities_from_module ( module) ;
320
- if let Some ( logs) = logs . open ( ) {
321
- logs . push ( format ! (
313
+ logs. add ( || {
314
+ format ! (
322
315
"Required capabilities: {}" ,
323
316
required_capabilities. to_string_limited( 20_000 )
324
- ) ) ;
325
- }
317
+ )
318
+ } ) ;
326
319
if !required_capabilities. is_subset ( available_capabilities) {
327
320
// We switch to BTreeSet to get a sorted error message
328
321
let unavailable: BTreeSet < _ > = required_capabilities
@@ -336,19 +329,16 @@ fn check_wasm_capabilities(
336
329
Ok ( ( ) )
337
330
}
338
331
339
- fn check_wasm_functions ( module : & ParsedWasm , mut logs : Logs ) -> VmResult < ( ) > {
340
- if let Some ( logs) = logs. open ( ) {
341
- logs. push ( format ! ( "Function count: {}" , module. function_count) ) ;
342
- logs. push ( format ! (
343
- "Max function parameters: {}" ,
344
- module. max_func_params
345
- ) ) ;
346
- logs. push ( format ! ( "Max function results: {}" , module. max_func_results) ) ;
347
- logs. push ( format ! (
332
+ fn check_wasm_functions ( module : & ParsedWasm , logs : Logger ) -> VmResult < ( ) > {
333
+ logs. add ( || format ! ( "Function count: {}" , module. function_count) ) ;
334
+ logs. add ( || format ! ( "Max function parameters: {}" , module. max_func_params) ) ;
335
+ logs. add ( || format ! ( "Max function results: {}" , module. max_func_results) ) ;
336
+ logs. add ( || {
337
+ format ! (
348
338
"Total function parameter count: {}" ,
349
339
module. total_func_params
350
- ) ) ;
351
- }
340
+ )
341
+ } ) ;
352
342
353
343
if module. function_count > MAX_FUNCTIONS {
354
344
return Err ( VmError :: static_validation_err ( format ! (
@@ -392,31 +382,6 @@ mod tests {
392
382
capabilities_from_csv ( "cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,iterator,staking,stargate" )
393
383
}
394
384
395
- #[ test]
396
- fn logs_works ( ) {
397
- let mut logs = Logs :: new ( ) ;
398
-
399
- if let Some ( logs) = logs. open ( ) {
400
- logs. push ( format ! ( "a test" ) ) ;
401
- }
402
-
403
- if let Some ( logs) = logs. open ( ) {
404
- logs. push ( format ! ( "second test" ) ) ;
405
- logs. push ( format ! ( "third test" ) ) ;
406
- }
407
-
408
- let mut logs_b = logs. clone ( ) ;
409
- if let Some ( logs) = logs_b. open ( ) {
410
- logs. push ( format ! ( "added in b" ) ) ;
411
- }
412
-
413
- let mut iter = logs. iter ( ) ;
414
- assert_eq ! ( iter. next( ) , Some ( String :: from( "a test" ) ) ) ;
415
- assert_eq ! ( iter. next( ) , Some ( String :: from( "second test" ) ) ) ;
416
- assert_eq ! ( iter. next( ) , Some ( String :: from( "third test" ) ) ) ;
417
- assert_eq ! ( iter. next( ) , None ) ;
418
- }
419
-
420
385
#[ test]
421
386
fn check_wasm_passes_for_latest_contract ( ) {
422
387
// this is our reference check, must pass
0 commit comments