@@ -41,6 +41,7 @@ type VM struct {
4141// `memoryLimit` is the memory limit of each contract execution (in MiB)
4242// `printDebug` is a flag to enable/disable printing debug logs from the contract to STDOUT. This should be false in production environments.
4343// `cacheSize` sets the size in MiB of an in-memory cache for e.g. module caching. Set to 0 to disable.
44+ // `deserCost` sets the gas cost of deserializing one byte of data.
4445func NewVM (dataDir string , supportedFeatures string , memoryLimit uint32 , printDebug bool , cacheSize uint32 ) (* VM , error ) {
4546 cache , err := api .InitCache (dataDir , supportedFeatures , cacheSize , memoryLimit )
4647 if err != nil {
@@ -124,6 +125,7 @@ func (vm *VM) Instantiate(
124125 querier Querier ,
125126 gasMeter GasMeter ,
126127 gasLimit uint64 ,
128+ deserCost types.UFraction ,
127129) (* types.Response , uint64 , error ) {
128130 envBin , err := json .Marshal (env )
129131 if err != nil {
@@ -138,6 +140,12 @@ func (vm *VM) Instantiate(
138140 return nil , gasUsed , err
139141 }
140142
143+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
144+ if gasLimit < gasForDeserialization + gasUsed {
145+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
146+ }
147+ gasUsed += gasForDeserialization
148+
141149 var result types.ContractResult
142150 err = json .Unmarshal (data , & result )
143151 if err != nil {
@@ -165,6 +173,7 @@ func (vm *VM) Execute(
165173 querier Querier ,
166174 gasMeter GasMeter ,
167175 gasLimit uint64 ,
176+ deserCost types.UFraction ,
168177) (* types.Response , uint64 , error ) {
169178 envBin , err := json .Marshal (env )
170179 if err != nil {
@@ -179,6 +188,12 @@ func (vm *VM) Execute(
179188 return nil , gasUsed , err
180189 }
181190
191+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
192+ if gasLimit < gasForDeserialization + gasUsed {
193+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
194+ }
195+
196+ gasUsed += gasForDeserialization
182197 var result types.ContractResult
183198 err = json .Unmarshal (data , & result )
184199 if err != nil {
@@ -202,6 +217,7 @@ func (vm *VM) Query(
202217 querier Querier ,
203218 gasMeter GasMeter ,
204219 gasLimit uint64 ,
220+ deserCost types.UFraction ,
205221) ([]byte , uint64 , error ) {
206222 envBin , err := json .Marshal (env )
207223 if err != nil {
@@ -212,6 +228,12 @@ func (vm *VM) Query(
212228 return nil , gasUsed , err
213229 }
214230
231+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
232+ if gasLimit < gasForDeserialization + gasUsed {
233+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
234+ }
235+ gasUsed += gasForDeserialization
236+
215237 var resp types.QueryResponse
216238 err = json .Unmarshal (data , & resp )
217239 if err != nil {
@@ -238,6 +260,7 @@ func (vm *VM) Migrate(
238260 querier Querier ,
239261 gasMeter GasMeter ,
240262 gasLimit uint64 ,
263+ deserCost types.UFraction ,
241264) (* types.Response , uint64 , error ) {
242265 envBin , err := json .Marshal (env )
243266 if err != nil {
@@ -248,6 +271,12 @@ func (vm *VM) Migrate(
248271 return nil , gasUsed , err
249272 }
250273
274+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
275+ if gasLimit < gasForDeserialization + gasUsed {
276+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
277+ }
278+ gasUsed += gasForDeserialization
279+
251280 var resp types.ContractResult
252281 err = json .Unmarshal (data , & resp )
253282 if err != nil {
@@ -274,6 +303,7 @@ func (vm *VM) Sudo(
274303 querier Querier ,
275304 gasMeter GasMeter ,
276305 gasLimit uint64 ,
306+ deserCost types.UFraction ,
277307) (* types.Response , uint64 , error ) {
278308 envBin , err := json .Marshal (env )
279309 if err != nil {
@@ -284,6 +314,12 @@ func (vm *VM) Sudo(
284314 return nil , gasUsed , err
285315 }
286316
317+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
318+ if gasLimit < gasForDeserialization + gasUsed {
319+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
320+ }
321+ gasUsed += gasForDeserialization
322+
287323 var resp types.ContractResult
288324 err = json .Unmarshal (data , & resp )
289325 if err != nil {
@@ -308,6 +344,7 @@ func (vm *VM) Reply(
308344 querier Querier ,
309345 gasMeter GasMeter ,
310346 gasLimit uint64 ,
347+ deserCost types.UFraction ,
311348) (* types.Response , uint64 , error ) {
312349 envBin , err := json .Marshal (env )
313350 if err != nil {
@@ -322,6 +359,12 @@ func (vm *VM) Reply(
322359 return nil , gasUsed , err
323360 }
324361
362+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
363+ if gasLimit < gasForDeserialization + gasUsed {
364+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
365+ }
366+ gasUsed += gasForDeserialization
367+
325368 var resp types.ContractResult
326369 err = json .Unmarshal (data , & resp )
327370 if err != nil {
@@ -344,6 +387,7 @@ func (vm *VM) IBCChannelOpen(
344387 querier Querier ,
345388 gasMeter GasMeter ,
346389 gasLimit uint64 ,
390+ deserCost types.UFraction ,
347391) (uint64 , error ) {
348392 envBin , err := json .Marshal (env )
349393 if err != nil {
@@ -358,6 +402,12 @@ func (vm *VM) IBCChannelOpen(
358402 return gasUsed , err
359403 }
360404
405+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
406+ if gasLimit < gasForDeserialization + gasUsed {
407+ return gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
408+ }
409+ gasUsed += gasForDeserialization
410+
361411 var resp types.IBCChannelOpenResult
362412 err = json .Unmarshal (data , & resp )
363413 if err != nil {
@@ -380,6 +430,7 @@ func (vm *VM) IBCChannelConnect(
380430 querier Querier ,
381431 gasMeter GasMeter ,
382432 gasLimit uint64 ,
433+ deserCost types.UFraction ,
383434) (* types.IBCBasicResponse , uint64 , error ) {
384435 envBin , err := json .Marshal (env )
385436 if err != nil {
@@ -394,6 +445,12 @@ func (vm *VM) IBCChannelConnect(
394445 return nil , gasUsed , err
395446 }
396447
448+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
449+ if gasLimit < gasForDeserialization + gasUsed {
450+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
451+ }
452+ gasUsed += gasForDeserialization
453+
397454 var resp types.IBCBasicResult
398455 err = json .Unmarshal (data , & resp )
399456 if err != nil {
@@ -416,6 +473,7 @@ func (vm *VM) IBCChannelClose(
416473 querier Querier ,
417474 gasMeter GasMeter ,
418475 gasLimit uint64 ,
476+ deserCost types.UFraction ,
419477) (* types.IBCBasicResponse , uint64 , error ) {
420478 envBin , err := json .Marshal (env )
421479 if err != nil {
@@ -430,6 +488,12 @@ func (vm *VM) IBCChannelClose(
430488 return nil , gasUsed , err
431489 }
432490
491+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
492+ if gasLimit < gasForDeserialization + gasUsed {
493+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
494+ }
495+ gasUsed += gasForDeserialization
496+
433497 var resp types.IBCBasicResult
434498 err = json .Unmarshal (data , & resp )
435499 if err != nil {
@@ -452,6 +516,7 @@ func (vm *VM) IBCPacketReceive(
452516 querier Querier ,
453517 gasMeter GasMeter ,
454518 gasLimit uint64 ,
519+ deserCost types.UFraction ,
455520) (* types.IBCReceiveResponse , uint64 , error ) {
456521 envBin , err := json .Marshal (env )
457522 if err != nil {
@@ -466,6 +531,12 @@ func (vm *VM) IBCPacketReceive(
466531 return nil , gasUsed , err
467532 }
468533
534+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
535+ if gasLimit < gasForDeserialization + gasUsed {
536+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
537+ }
538+ gasUsed += gasForDeserialization
539+
469540 var resp types.IBCReceiveResult
470541 err = json .Unmarshal (data , & resp )
471542 if err != nil {
@@ -489,6 +560,7 @@ func (vm *VM) IBCPacketAck(
489560 querier Querier ,
490561 gasMeter GasMeter ,
491562 gasLimit uint64 ,
563+ deserCost types.UFraction ,
492564) (* types.IBCBasicResponse , uint64 , error ) {
493565 envBin , err := json .Marshal (env )
494566 if err != nil {
@@ -503,6 +575,12 @@ func (vm *VM) IBCPacketAck(
503575 return nil , gasUsed , err
504576 }
505577
578+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
579+ if gasLimit < gasForDeserialization + gasUsed {
580+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
581+ }
582+ gasUsed += gasForDeserialization
583+
506584 var resp types.IBCBasicResult
507585 err = json .Unmarshal (data , & resp )
508586 if err != nil {
@@ -526,6 +604,7 @@ func (vm *VM) IBCPacketTimeout(
526604 querier Querier ,
527605 gasMeter GasMeter ,
528606 gasLimit uint64 ,
607+ deserCost types.UFraction ,
529608) (* types.IBCBasicResponse , uint64 , error ) {
530609 envBin , err := json .Marshal (env )
531610 if err != nil {
@@ -540,6 +619,12 @@ func (vm *VM) IBCPacketTimeout(
540619 return nil , gasUsed , err
541620 }
542621
622+ gasForDeserialization := deserCost .Mul (uint64 (len (data ))).Floor ()
623+ if gasLimit < gasForDeserialization + gasUsed {
624+ return nil , gasUsed , fmt .Errorf ("Insufficient gas left to deserialize contract execution result (%d bytes)" , len (data ))
625+ }
626+ gasUsed += gasForDeserialization
627+
543628 var resp types.IBCBasicResult
544629 err = json .Unmarshal (data , & resp )
545630 if err != nil {
0 commit comments