github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/keeper/gas_register_test.go (about)

     1  package keeper
     2  
     3  import (
     4  	"math"
     5  	"strings"
     6  	"testing"
     7  
     8  	wasmvmtypes "github.com/CosmWasm/wasmvm/types"
     9  	storetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
    10  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func TestCompileCosts(t *testing.T) {
    15  	specs := map[string]struct {
    16  		srcLen    int
    17  		srcConfig WasmGasRegisterConfig
    18  		exp       sdk.Gas
    19  		expPanic  bool
    20  	}{
    21  		"one byte": {
    22  			srcLen:    1,
    23  			srcConfig: DefaultGasRegisterConfig(),
    24  			exp:       sdk.Gas(3), // DefaultCompileCost
    25  		},
    26  		"zero byte": {
    27  			srcLen:    0,
    28  			srcConfig: DefaultGasRegisterConfig(),
    29  			exp:       sdk.Gas(0),
    30  		},
    31  		"negative len": {
    32  			srcLen:    -1,
    33  			srcConfig: DefaultGasRegisterConfig(),
    34  			expPanic:  true,
    35  		},
    36  	}
    37  	for name, spec := range specs {
    38  		t.Run(name, func(t *testing.T) {
    39  			if spec.expPanic {
    40  				assert.Panics(t, func() {
    41  					NewWasmGasRegister(spec.srcConfig).CompileCosts(spec.srcLen)
    42  				})
    43  				return
    44  			}
    45  			gotGas := NewWasmGasRegister(spec.srcConfig).CompileCosts(spec.srcLen)
    46  			assert.Equal(t, spec.exp, gotGas)
    47  		})
    48  	}
    49  }
    50  
    51  func TestNewContractInstanceCosts(t *testing.T) {
    52  	specs := map[string]struct {
    53  		srcLen    int
    54  		srcConfig WasmGasRegisterConfig
    55  		pinned    bool
    56  		exp       sdk.Gas
    57  		expPanic  bool
    58  	}{
    59  		"small msg - pinned": {
    60  			srcLen:    1,
    61  			srcConfig: DefaultGasRegisterConfig(),
    62  			pinned:    true,
    63  			exp:       DefaultContractMessageDataCost,
    64  		},
    65  		"big msg - pinned": {
    66  			srcLen:    math.MaxUint32,
    67  			srcConfig: DefaultGasRegisterConfig(),
    68  			pinned:    true,
    69  			exp:       DefaultContractMessageDataCost * sdk.Gas(math.MaxUint32),
    70  		},
    71  		"empty msg - pinned": {
    72  			srcLen:    0,
    73  			pinned:    true,
    74  			srcConfig: DefaultGasRegisterConfig(),
    75  			exp:       sdk.Gas(0),
    76  		},
    77  		"small msg - unpinned": {
    78  			srcLen:    1,
    79  			srcConfig: DefaultGasRegisterConfig(),
    80  			exp:       DefaultContractMessageDataCost + DefaultInstanceCost,
    81  		},
    82  		"big msg - unpinned": {
    83  			srcLen:    math.MaxUint32,
    84  			srcConfig: DefaultGasRegisterConfig(),
    85  			exp:       sdk.Gas(DefaultContractMessageDataCost*math.MaxUint32 + DefaultInstanceCost),
    86  		},
    87  		"empty msg - unpinned": {
    88  			srcLen:    0,
    89  			srcConfig: DefaultGasRegisterConfig(),
    90  			exp:       sdk.Gas(DefaultInstanceCost),
    91  		},
    92  
    93  		"negative len": {
    94  			srcLen:    -1,
    95  			srcConfig: DefaultGasRegisterConfig(),
    96  			expPanic:  true,
    97  		},
    98  	}
    99  	for name, spec := range specs {
   100  		t.Run(name, func(t *testing.T) {
   101  			if spec.expPanic {
   102  				assert.Panics(t, func() {
   103  					NewWasmGasRegister(spec.srcConfig).NewContractInstanceCosts(spec.pinned, spec.srcLen)
   104  				})
   105  				return
   106  			}
   107  			gotGas := NewWasmGasRegister(spec.srcConfig).NewContractInstanceCosts(spec.pinned, spec.srcLen)
   108  			assert.Equal(t, spec.exp, gotGas)
   109  		})
   110  	}
   111  }
   112  
   113  func TestContractInstanceCosts(t *testing.T) {
   114  	// same as TestNewContractInstanceCosts currently
   115  	specs := map[string]struct {
   116  		srcLen    int
   117  		srcConfig WasmGasRegisterConfig
   118  		pinned    bool
   119  		exp       sdk.Gas
   120  		expPanic  bool
   121  	}{
   122  		"small msg - pinned": {
   123  			srcLen:    1,
   124  			srcConfig: DefaultGasRegisterConfig(),
   125  			pinned:    true,
   126  			exp:       DefaultContractMessageDataCost,
   127  		},
   128  		"big msg - pinned": {
   129  			srcLen:    math.MaxUint32,
   130  			srcConfig: DefaultGasRegisterConfig(),
   131  			pinned:    true,
   132  			exp:       sdk.Gas(DefaultContractMessageDataCost * math.MaxUint32),
   133  		},
   134  		"empty msg - pinned": {
   135  			srcLen:    0,
   136  			pinned:    true,
   137  			srcConfig: DefaultGasRegisterConfig(),
   138  			exp:       sdk.Gas(0),
   139  		},
   140  		"small msg - unpinned": {
   141  			srcLen:    1,
   142  			srcConfig: DefaultGasRegisterConfig(),
   143  			exp:       DefaultContractMessageDataCost + DefaultInstanceCost,
   144  		},
   145  		"big msg - unpinned": {
   146  			srcLen:    math.MaxUint32,
   147  			srcConfig: DefaultGasRegisterConfig(),
   148  			exp:       sdk.Gas(DefaultContractMessageDataCost*math.MaxUint32 + DefaultInstanceCost),
   149  		},
   150  		"empty msg - unpinned": {
   151  			srcLen:    0,
   152  			srcConfig: DefaultGasRegisterConfig(),
   153  			exp:       sdk.Gas(DefaultInstanceCost),
   154  		},
   155  
   156  		"negative len": {
   157  			srcLen:    -1,
   158  			srcConfig: DefaultGasRegisterConfig(),
   159  			expPanic:  true,
   160  		},
   161  	}
   162  	for name, spec := range specs {
   163  		t.Run(name, func(t *testing.T) {
   164  			if spec.expPanic {
   165  				assert.Panics(t, func() {
   166  					NewWasmGasRegister(spec.srcConfig).InstantiateContractCosts(spec.pinned, spec.srcLen)
   167  				})
   168  				return
   169  			}
   170  			gotGas := NewWasmGasRegister(spec.srcConfig).InstantiateContractCosts(spec.pinned, spec.srcLen)
   171  			assert.Equal(t, spec.exp, gotGas)
   172  		})
   173  	}
   174  }
   175  
   176  func TestReplyCost(t *testing.T) {
   177  	specs := map[string]struct {
   178  		src       wasmvmtypes.Reply
   179  		srcConfig WasmGasRegisterConfig
   180  		pinned    bool
   181  		exp       sdk.Gas
   182  		expPanic  bool
   183  	}{
   184  		"subcall response with events and data - pinned": {
   185  			src: wasmvmtypes.Reply{
   186  				Result: wasmvmtypes.SubMsgResult{
   187  					Ok: &wasmvmtypes.SubMsgResponse{
   188  						Events: []wasmvmtypes.Event{
   189  							{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
   190  						},
   191  						Data: []byte{0x1},
   192  					},
   193  				},
   194  			},
   195  			srcConfig: DefaultGasRegisterConfig(),
   196  			pinned:    true,
   197  			exp:       sdk.Gas(3*DefaultEventAttributeDataCost + DefaultPerAttributeCost + DefaultContractMessageDataCost), // 3 == len("foo")
   198  		},
   199  		"subcall response with events - pinned": {
   200  			src: wasmvmtypes.Reply{
   201  				Result: wasmvmtypes.SubMsgResult{
   202  					Ok: &wasmvmtypes.SubMsgResponse{
   203  						Events: []wasmvmtypes.Event{
   204  							{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
   205  						},
   206  					},
   207  				},
   208  			},
   209  			srcConfig: DefaultGasRegisterConfig(),
   210  			pinned:    true,
   211  			exp:       sdk.Gas(3*DefaultEventAttributeDataCost + DefaultPerAttributeCost), // 3 == len("foo")
   212  		},
   213  		"subcall response with events exceeds free tier- pinned": {
   214  			src: wasmvmtypes.Reply{
   215  				Result: wasmvmtypes.SubMsgResult{
   216  					Ok: &wasmvmtypes.SubMsgResponse{
   217  						Events: []wasmvmtypes.Event{
   218  							{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: strings.Repeat("x", DefaultEventAttributeDataFreeTier), Value: "myData"}}},
   219  						},
   220  					},
   221  				},
   222  			},
   223  			srcConfig: DefaultGasRegisterConfig(),
   224  			pinned:    true,
   225  			exp:       sdk.Gas((3+6)*DefaultEventAttributeDataCost + DefaultPerAttributeCost), // 3 == len("foo"), 6 == len("myData")
   226  		},
   227  		"subcall response error - pinned": {
   228  			src: wasmvmtypes.Reply{
   229  				Result: wasmvmtypes.SubMsgResult{
   230  					Err: "foo",
   231  				},
   232  			},
   233  			srcConfig: DefaultGasRegisterConfig(),
   234  			pinned:    true,
   235  			exp:       3 * DefaultContractMessageDataCost,
   236  		},
   237  		"subcall response with events and data - unpinned": {
   238  			src: wasmvmtypes.Reply{
   239  				Result: wasmvmtypes.SubMsgResult{
   240  					Ok: &wasmvmtypes.SubMsgResponse{
   241  						Events: []wasmvmtypes.Event{
   242  							{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
   243  						},
   244  						Data: []byte{0x1},
   245  					},
   246  				},
   247  			},
   248  			srcConfig: DefaultGasRegisterConfig(),
   249  			exp:       sdk.Gas(DefaultInstanceCost + 3*DefaultEventAttributeDataCost + DefaultPerAttributeCost + DefaultContractMessageDataCost),
   250  		},
   251  		"subcall response with events - unpinned": {
   252  			src: wasmvmtypes.Reply{
   253  				Result: wasmvmtypes.SubMsgResult{
   254  					Ok: &wasmvmtypes.SubMsgResponse{
   255  						Events: []wasmvmtypes.Event{
   256  							{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
   257  						},
   258  					},
   259  				},
   260  			},
   261  			srcConfig: DefaultGasRegisterConfig(),
   262  			exp:       sdk.Gas(DefaultInstanceCost + 3*DefaultEventAttributeDataCost + DefaultPerAttributeCost),
   263  		},
   264  		"subcall response with events exceeds free tier- unpinned": {
   265  			src: wasmvmtypes.Reply{
   266  				Result: wasmvmtypes.SubMsgResult{
   267  					Ok: &wasmvmtypes.SubMsgResponse{
   268  						Events: []wasmvmtypes.Event{
   269  							{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: strings.Repeat("x", DefaultEventAttributeDataFreeTier), Value: "myData"}}},
   270  						},
   271  					},
   272  				},
   273  			},
   274  			srcConfig: DefaultGasRegisterConfig(),
   275  			exp:       sdk.Gas(DefaultInstanceCost + (3+6)*DefaultEventAttributeDataCost + DefaultPerAttributeCost), // 3 == len("foo"), 6 == len("myData")
   276  		},
   277  		"subcall response error - unpinned": {
   278  			src: wasmvmtypes.Reply{
   279  				Result: wasmvmtypes.SubMsgResult{
   280  					Err: "foo",
   281  				},
   282  			},
   283  			srcConfig: DefaultGasRegisterConfig(),
   284  			exp:       sdk.Gas(DefaultInstanceCost + 3*DefaultContractMessageDataCost),
   285  		},
   286  		"subcall response with empty events": {
   287  			src: wasmvmtypes.Reply{
   288  				Result: wasmvmtypes.SubMsgResult{
   289  					Ok: &wasmvmtypes.SubMsgResponse{
   290  						Events: make([]wasmvmtypes.Event, 10),
   291  					},
   292  				},
   293  			},
   294  			srcConfig: DefaultGasRegisterConfig(),
   295  			exp:       DefaultInstanceCost,
   296  		},
   297  		"subcall response with events unset": {
   298  			src: wasmvmtypes.Reply{
   299  				Result: wasmvmtypes.SubMsgResult{
   300  					Ok: &wasmvmtypes.SubMsgResponse{},
   301  				},
   302  			},
   303  			srcConfig: DefaultGasRegisterConfig(),
   304  			exp:       DefaultInstanceCost,
   305  		},
   306  	}
   307  	for name, spec := range specs {
   308  		t.Run(name, func(t *testing.T) {
   309  			if spec.expPanic {
   310  				assert.Panics(t, func() {
   311  					NewWasmGasRegister(spec.srcConfig).ReplyCosts(spec.pinned, spec.src)
   312  				})
   313  				return
   314  			}
   315  			gotGas := NewWasmGasRegister(spec.srcConfig).ReplyCosts(spec.pinned, spec.src)
   316  			assert.Equal(t, spec.exp, gotGas)
   317  		})
   318  	}
   319  }
   320  
   321  func TestEventCosts(t *testing.T) {
   322  	// most cases are covered in TestReplyCost already. This ensures some edge cases
   323  	specs := map[string]struct {
   324  		srcAttrs  []wasmvmtypes.EventAttribute
   325  		srcEvents wasmvmtypes.Events
   326  		expGas    sdk.Gas
   327  	}{
   328  		"empty events": {
   329  			srcEvents: make([]wasmvmtypes.Event, 1),
   330  			expGas:    DefaultPerCustomEventCost,
   331  		},
   332  		"empty attributes": {
   333  			srcAttrs: make([]wasmvmtypes.EventAttribute, 1),
   334  			expGas:   DefaultPerAttributeCost,
   335  		},
   336  		"both nil": {
   337  			expGas: 0,
   338  		},
   339  	}
   340  	for name, spec := range specs {
   341  		t.Run(name, func(t *testing.T) {
   342  			gotGas := NewDefaultWasmGasRegister().EventCosts(spec.srcAttrs, spec.srcEvents)
   343  			assert.Equal(t, spec.expGas, gotGas)
   344  		})
   345  	}
   346  }
   347  
   348  func TestToWasmVMGasConversion(t *testing.T) {
   349  	specs := map[string]struct {
   350  		src       storetypes.Gas
   351  		srcConfig WasmGasRegisterConfig
   352  		exp       uint64
   353  		expPanic  bool
   354  	}{
   355  		"0": {
   356  			src:       0,
   357  			exp:       0,
   358  			srcConfig: DefaultGasRegisterConfig(),
   359  		},
   360  		"max": {
   361  			srcConfig: WasmGasRegisterConfig{
   362  				GasMultiplier: 1,
   363  			},
   364  			src: math.MaxUint64,
   365  			exp: math.MaxUint64,
   366  		},
   367  		"overflow": {
   368  			srcConfig: WasmGasRegisterConfig{
   369  				GasMultiplier: 2,
   370  			},
   371  			src:      math.MaxUint64,
   372  			expPanic: true,
   373  		},
   374  	}
   375  	for name, spec := range specs {
   376  		t.Run(name, func(t *testing.T) {
   377  			if spec.expPanic {
   378  				assert.Panics(t, func() {
   379  					r := NewWasmGasRegister(spec.srcConfig)
   380  					_ = r.ToWasmVMGas(spec.src)
   381  				})
   382  				return
   383  			}
   384  			r := NewWasmGasRegister(spec.srcConfig)
   385  			got := r.ToWasmVMGas(spec.src)
   386  			assert.Equal(t, spec.exp, got)
   387  		})
   388  	}
   389  }
   390  
   391  func TestFromWasmVMGasConversion(t *testing.T) {
   392  	specs := map[string]struct {
   393  		src       uint64
   394  		exp       storetypes.Gas
   395  		srcConfig WasmGasRegisterConfig
   396  		expPanic  bool
   397  	}{
   398  		"0": {
   399  			src:       0,
   400  			exp:       0,
   401  			srcConfig: DefaultGasRegisterConfig(),
   402  		},
   403  		"max": {
   404  			srcConfig: WasmGasRegisterConfig{
   405  				GasMultiplier: 1,
   406  			},
   407  			src: math.MaxUint64,
   408  			exp: math.MaxUint64,
   409  		},
   410  		"missconfigured": {
   411  			srcConfig: WasmGasRegisterConfig{
   412  				GasMultiplier: 0,
   413  			},
   414  			src:      1,
   415  			expPanic: true,
   416  		},
   417  	}
   418  	for name, spec := range specs {
   419  		t.Run(name, func(t *testing.T) {
   420  			if spec.expPanic {
   421  				assert.Panics(t, func() {
   422  					r := NewWasmGasRegister(spec.srcConfig)
   423  					_ = r.FromWasmVMGas(spec.src)
   424  				})
   425  				return
   426  			}
   427  			r := NewWasmGasRegister(spec.srcConfig)
   428  			got := r.FromWasmVMGas(spec.src)
   429  			assert.Equal(t, spec.exp, got)
   430  		})
   431  	}
   432  }