1
- use std:: cell:: RefCell ;
2
- use std:: cell:: RefMut ;
3
1
use std:: collections:: BTreeSet ;
4
2
use std:: collections:: HashSet ;
5
3
@@ -99,70 +97,59 @@ const MAX_TOTAL_FUNCTION_PARAMS: usize = 10_000;
99
97
/// during static validation.
100
98
const MAX_FUNCTION_RESULTS : usize = 1 ;
101
99
102
- #[ derive( Clone , Default ) ]
103
- pub enum Logs {
104
- 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
+ } ,
105
111
#[ default]
106
112
Off ,
107
113
}
108
114
109
- pub struct LogAccess < ' a > ( RefMut < ' a , Vec < String > > ) ;
110
-
111
- impl < ' a > LogAccess < ' a > {
112
- /// Adds a message to the logs
113
- pub fn add ( & mut self , msg : impl Into < String > ) {
114
- self . 0 . push ( msg. into ( ) ) ;
115
- }
116
- }
117
-
118
- impl Logs {
115
+ impl < ' a > Logger < ' a > {
119
116
pub fn new ( ) -> Self {
120
- On ( RefCell :: new ( Vec :: new ( ) ) )
117
+ On {
118
+ output : LogOutput :: StdOut ,
119
+ prefix : "" ,
120
+ }
121
121
}
122
122
123
- // Gets access to logs for writing.
124
- // Use this if you want to add multiple messages at once.
125
- pub fn open ( & mut self ) -> Option < LogAccess > {
126
- match self {
127
- On ( data) => Some ( LogAccess ( data. borrow_mut ( ) ) ) ,
128
- Off => None ,
129
- }
123
+ pub fn with_config ( output : LogOutput , prefix : & ' a str ) -> Self {
124
+ On { output, prefix }
130
125
}
131
126
132
127
/// Adds a message to the logs, if they are enabled.
133
128
/// This is a convenience method for adding a single message.
134
129
///
135
130
/// Takes a closure that returns the message to add to avoid unnecessary allocations.
136
- pub fn add ( & mut self , msg_fn : impl FnOnce ( ) -> String ) {
137
- if let Some ( mut logs) = self . open ( ) {
138
- logs. add ( msg_fn ( ) ) ;
139
- }
140
- }
141
- }
142
-
143
- impl IntoIterator for Logs {
144
- type Item = String ;
145
- type IntoIter = std:: vec:: IntoIter < Self :: Item > ;
146
-
147
- fn into_iter ( self ) -> Self :: IntoIter {
148
- match self {
149
- Logs :: On ( data) => data. into_inner ( ) . into_iter ( ) ,
150
- Logs :: Off => vec ! [ ] . into_iter ( ) ,
131
+ pub fn add ( & self , msg_fn : impl FnOnce ( ) -> String ) {
132
+ if let On { prefix, output } = & self {
133
+ let msg = msg_fn ( ) ;
134
+ match output {
135
+ LogOutput :: StdOut => println ! ( "{prefix}{msg}" ) ,
136
+ LogOutput :: StdErr => eprintln ! ( "{prefix}{msg}" ) ,
137
+ }
151
138
}
152
139
}
153
140
}
154
141
155
- use Logs :: * ;
142
+ use Logger :: * ;
156
143
157
144
/// Checks if the data is valid wasm and compatibility with the CosmWasm API (imports and exports)
158
145
pub fn check_wasm ( wasm_code : & [ u8 ] , available_capabilities : & HashSet < String > ) -> VmResult < ( ) > {
159
- check_wasm_with_logs ( wasm_code, available_capabilities, & mut Off )
146
+ check_wasm_with_logs ( wasm_code, available_capabilities, Off )
160
147
}
161
148
162
- pub fn check_wasm_with_logs (
149
+ pub fn check_wasm_with_logs < ' a > (
163
150
wasm_code : & [ u8 ] ,
164
151
available_capabilities : & HashSet < String > ,
165
- logs : & mut Logs ,
152
+ logs : Logger < ' a > ,
166
153
) -> VmResult < ( ) > {
167
154
logs. add ( || format ! ( "Size of Wasm blob: {}" , wasm_code. len( ) ) ) ;
168
155
@@ -255,7 +242,7 @@ fn check_interface_version(module: &ParsedWasm) -> VmResult<()> {
255
242
}
256
243
}
257
244
258
- fn check_wasm_exports ( module : & ParsedWasm , logs : & mut Logs ) -> VmResult < ( ) > {
245
+ fn check_wasm_exports ( module : & ParsedWasm , logs : Logger ) -> VmResult < ( ) > {
259
246
let available_exports: HashSet < String > = module. exported_function_names ( None ) ;
260
247
261
248
logs. add ( || format ! ( "Exports: {}" , available_exports. to_string_limited( 20_000 ) ) ) ;
@@ -276,7 +263,7 @@ fn check_wasm_exports(module: &ParsedWasm, logs: &mut Logs) -> VmResult<()> {
276
263
fn check_wasm_imports (
277
264
module : & ParsedWasm ,
278
265
supported_imports : & [ & str ] ,
279
- logs : & mut Logs ,
266
+ logs : Logger ,
280
267
) -> VmResult < ( ) > {
281
268
logs. add ( || {
282
269
format ! (
@@ -327,7 +314,7 @@ fn full_import_name(ie: &Import) -> String {
327
314
fn check_wasm_capabilities (
328
315
module : & ParsedWasm ,
329
316
available_capabilities : & HashSet < String > ,
330
- logs : & mut Logs ,
317
+ logs : Logger ,
331
318
) -> VmResult < ( ) > {
332
319
let required_capabilities = required_capabilities_from_module ( module) ;
333
320
logs. add ( || {
@@ -349,19 +336,16 @@ fn check_wasm_capabilities(
349
336
Ok ( ( ) )
350
337
}
351
338
352
- fn check_wasm_functions ( module : & ParsedWasm , logs : & mut Logs ) -> VmResult < ( ) > {
353
- if let Some ( mut logs) = logs. open ( ) {
354
- logs. add ( format ! ( "Function count: {}" , module. function_count) ) ;
355
- logs. add ( format ! (
356
- "Max function parameters: {}" ,
357
- module. max_func_params
358
- ) ) ;
359
- logs. add ( format ! ( "Max function results: {}" , module. max_func_results) ) ;
360
- logs. add ( format ! (
339
+ fn check_wasm_functions ( module : & ParsedWasm , logs : Logger ) -> VmResult < ( ) > {
340
+ logs. add ( || format ! ( "Function count: {}" , module. function_count) ) ;
341
+ logs. add ( || format ! ( "Max function parameters: {}" , module. max_func_params) ) ;
342
+ logs. add ( || format ! ( "Max function results: {}" , module. max_func_results) ) ;
343
+ logs. add ( || {
344
+ format ! (
361
345
"Total function parameter count: {}" ,
362
346
module. total_func_params
363
- ) ) ;
364
- }
347
+ )
348
+ } ) ;
365
349
366
350
if module. function_count > MAX_FUNCTIONS {
367
351
return Err ( VmError :: static_validation_err ( format ! (
@@ -405,29 +389,6 @@ mod tests {
405
389
capabilities_from_csv ( "cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,iterator,staking,stargate" )
406
390
}
407
391
408
- #[ test]
409
- fn logs_works ( ) {
410
- let mut logs = Logs :: new ( ) ;
411
-
412
- logs. add ( || "a test" . to_string ( ) ) ;
413
-
414
- if let Some ( mut logs) = logs. open ( ) {
415
- logs. add ( "second test" ) ;
416
- logs. add ( "third test" ) ;
417
- }
418
-
419
- let mut logs_b = logs. clone ( ) ;
420
- if let Some ( mut logs) = logs_b. open ( ) {
421
- logs. add ( "added in b" ) ;
422
- }
423
-
424
- let mut iter = logs. into_iter ( ) ;
425
- assert_eq ! ( iter. next( ) , Some ( String :: from( "a test" ) ) ) ;
426
- assert_eq ! ( iter. next( ) , Some ( String :: from( "second test" ) ) ) ;
427
- assert_eq ! ( iter. next( ) , Some ( String :: from( "third test" ) ) ) ;
428
- assert_eq ! ( iter. next( ) , None ) ;
429
- }
430
-
431
392
#[ test]
432
393
fn check_wasm_passes_for_latest_contract ( ) {
433
394
// this is our reference check, must pass
@@ -729,7 +690,7 @@ mod tests {
729
690
)
730
691
. unwrap ( ) ;
731
692
let module = ParsedWasm :: parse ( & wasm) . unwrap ( ) ;
732
- check_wasm_exports ( & module, & mut Off ) . unwrap ( ) ;
693
+ check_wasm_exports ( & module, Off ) . unwrap ( ) ;
733
694
734
695
// this is invalid, as it doesn't any required export
735
696
let wasm = wat:: parse_str (
@@ -741,7 +702,7 @@ mod tests {
741
702
)
742
703
. unwrap ( ) ;
743
704
let module = ParsedWasm :: parse ( & wasm) . unwrap ( ) ;
744
- match check_wasm_exports ( & module, & mut Off ) {
705
+ match check_wasm_exports ( & module, Off ) {
745
706
Err ( VmError :: StaticValidationErr { msg, .. } ) => {
746
707
assert ! ( msg. starts_with( "Wasm contract doesn't have required export: \" allocate\" " ) ) ;
747
708
}
@@ -760,7 +721,7 @@ mod tests {
760
721
)
761
722
. unwrap ( ) ;
762
723
let module = ParsedWasm :: parse ( & wasm) . unwrap ( ) ;
763
- match check_wasm_exports ( & module, & mut Off ) {
724
+ match check_wasm_exports ( & module, Off ) {
764
725
Err ( VmError :: StaticValidationErr { msg, .. } ) => {
765
726
assert ! (
766
727
msg. starts_with( "Wasm contract doesn't have required export: \" deallocate\" " )
@@ -790,12 +751,7 @@ mod tests {
790
751
)"# ,
791
752
)
792
753
. unwrap ( ) ;
793
- check_wasm_imports (
794
- & ParsedWasm :: parse ( & wasm) . unwrap ( ) ,
795
- SUPPORTED_IMPORTS ,
796
- & mut Off ,
797
- )
798
- . unwrap ( ) ;
754
+ check_wasm_imports ( & ParsedWasm :: parse ( & wasm) . unwrap ( ) , SUPPORTED_IMPORTS , Off ) . unwrap ( ) ;
799
755
}
800
756
801
757
#[ test]
@@ -906,12 +862,8 @@ mod tests {
906
862
)"# ,
907
863
)
908
864
. unwrap ( ) ;
909
- let err = check_wasm_imports (
910
- & ParsedWasm :: parse ( & wasm) . unwrap ( ) ,
911
- SUPPORTED_IMPORTS ,
912
- & mut Off ,
913
- )
914
- . unwrap_err ( ) ;
865
+ let err = check_wasm_imports ( & ParsedWasm :: parse ( & wasm) . unwrap ( ) , SUPPORTED_IMPORTS , Off )
866
+ . unwrap_err ( ) ;
915
867
match err {
916
868
VmError :: StaticValidationErr { msg, .. } => {
917
869
assert_eq ! ( msg, "Import count exceeds limit. Imports: 101. Limit: 100." ) ;
@@ -948,11 +900,7 @@ mod tests {
948
900
"env.debug" ,
949
901
"env.query_chain" ,
950
902
] ;
951
- let result = check_wasm_imports (
952
- & ParsedWasm :: parse ( & wasm) . unwrap ( ) ,
953
- supported_imports,
954
- & mut Off ,
955
- ) ;
903
+ let result = check_wasm_imports ( & ParsedWasm :: parse ( & wasm) . unwrap ( ) , supported_imports, Off ) ;
956
904
match result. unwrap_err ( ) {
957
905
VmError :: StaticValidationErr { msg, .. } => {
958
906
println ! ( "{msg}" ) ;
@@ -968,7 +916,7 @@ mod tests {
968
916
#[ test]
969
917
fn check_wasm_imports_of_old_contract ( ) {
970
918
let module = & ParsedWasm :: parse ( CONTRACT_0_7 ) . unwrap ( ) ;
971
- let result = check_wasm_imports ( module, SUPPORTED_IMPORTS , & mut Off ) ;
919
+ let result = check_wasm_imports ( module, SUPPORTED_IMPORTS , Off ) ;
972
920
match result. unwrap_err ( ) {
973
921
VmError :: StaticValidationErr { msg, .. } => {
974
922
assert ! (
@@ -982,11 +930,7 @@ mod tests {
982
930
#[ test]
983
931
fn check_wasm_imports_wrong_type ( ) {
984
932
let wasm = wat:: parse_str ( r#"(module (import "env" "db_read" (memory 1 1)))"# ) . unwrap ( ) ;
985
- let result = check_wasm_imports (
986
- & ParsedWasm :: parse ( & wasm) . unwrap ( ) ,
987
- SUPPORTED_IMPORTS ,
988
- & mut Off ,
989
- ) ;
933
+ let result = check_wasm_imports ( & ParsedWasm :: parse ( & wasm) . unwrap ( ) , SUPPORTED_IMPORTS , Off ) ;
990
934
match result. unwrap_err ( ) {
991
935
VmError :: StaticValidationErr { msg, .. } => {
992
936
assert ! (
@@ -1021,7 +965,7 @@ mod tests {
1021
965
]
1022
966
. into_iter ( )
1023
967
. collect ( ) ;
1024
- check_wasm_capabilities ( & module, & available, & mut Off ) . unwrap ( ) ;
968
+ check_wasm_capabilities ( & module, & available, Off ) . unwrap ( ) ;
1025
969
}
1026
970
1027
971
#[ test]
@@ -1049,7 +993,7 @@ mod tests {
1049
993
]
1050
994
. into_iter ( )
1051
995
. collect ( ) ;
1052
- match check_wasm_capabilities ( & module, & available, & mut Off ) . unwrap_err ( ) {
996
+ match check_wasm_capabilities ( & module, & available, Off ) . unwrap_err ( ) {
1053
997
VmError :: StaticValidationErr { msg, .. } => assert_eq ! (
1054
998
msg,
1055
999
"Wasm contract requires unavailable capabilities: {\" sun\" }"
@@ -1065,7 +1009,7 @@ mod tests {
1065
1009
]
1066
1010
. into_iter ( )
1067
1011
. collect ( ) ;
1068
- match check_wasm_capabilities ( & module, & available, & mut Off ) . unwrap_err ( ) {
1012
+ match check_wasm_capabilities ( & module, & available, Off ) . unwrap_err ( ) {
1069
1013
VmError :: StaticValidationErr { msg, .. } => assert_eq ! (
1070
1014
msg,
1071
1015
"Wasm contract requires unavailable capabilities: {\" sun\" , \" water\" }"
@@ -1075,7 +1019,7 @@ mod tests {
1075
1019
1076
1020
// Available set 3
1077
1021
let available = [ "freedom" . to_string ( ) ] . into_iter ( ) . collect ( ) ;
1078
- match check_wasm_capabilities ( & module, & available, & mut Off ) . unwrap_err ( ) {
1022
+ match check_wasm_capabilities ( & module, & available, Off ) . unwrap_err ( ) {
1079
1023
VmError :: StaticValidationErr { msg, .. } => assert_eq ! (
1080
1024
msg,
1081
1025
"Wasm contract requires unavailable capabilities: {\" nutrients\" , \" sun\" , \" water\" }"
@@ -1085,7 +1029,7 @@ mod tests {
1085
1029
1086
1030
// Available set 4
1087
1031
let available = [ ] . into_iter ( ) . collect ( ) ;
1088
- match check_wasm_capabilities ( & module, & available, & mut Off ) . unwrap_err ( ) {
1032
+ match check_wasm_capabilities ( & module, & available, Off ) . unwrap_err ( ) {
1089
1033
VmError :: StaticValidationErr { msg, .. } => assert_eq ! (
1090
1034
msg,
1091
1035
"Wasm contract requires unavailable capabilities: {\" nutrients\" , \" sun\" , \" water\" }"
@@ -1107,7 +1051,7 @@ mod tests {
1107
1051
. unwrap ( ) ;
1108
1052
let module = ParsedWasm :: parse ( & wasm) . unwrap ( ) ;
1109
1053
1110
- match check_wasm_functions ( & module, & mut Off ) . unwrap_err ( ) {
1054
+ match check_wasm_functions ( & module, Off ) . unwrap_err ( ) {
1111
1055
VmError :: StaticValidationErr { msg, .. } => assert_eq ! (
1112
1056
msg,
1113
1057
"Wasm contract contains function with more than 100 parameters"
@@ -1126,7 +1070,7 @@ mod tests {
1126
1070
) )
1127
1071
. unwrap ( ) ;
1128
1072
let module = ParsedWasm :: parse ( & wasm) . unwrap ( ) ;
1129
- match check_wasm_functions ( & module, & mut Off ) . unwrap_err ( ) {
1073
+ match check_wasm_functions ( & module, Off ) . unwrap_err ( ) {
1130
1074
VmError :: StaticValidationErr { msg, .. } => assert_eq ! (
1131
1075
msg,
1132
1076
"Wasm contract contains function with more than 1 results"
@@ -1145,7 +1089,7 @@ mod tests {
1145
1089
) )
1146
1090
. unwrap ( ) ;
1147
1091
let module = ParsedWasm :: parse ( & wasm) . unwrap ( ) ;
1148
- match check_wasm_functions ( & module, & mut Off ) . unwrap_err ( ) {
1092
+ match check_wasm_functions ( & module, Off ) . unwrap_err ( ) {
1149
1093
VmError :: StaticValidationErr { msg, .. } => {
1150
1094
assert_eq ! ( msg, "Wasm contract contains more than 20000 functions" )
1151
1095
}
0 commit comments