github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/engine_v8_test.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package nvm
    20  
    21  import (
    22  	"bufio"
    23  	"bytes"
    24  	"encoding/json"
    25  	"fmt"
    26  	"io/ioutil"
    27  	"os"
    28  	"strings"
    29  	"sync"
    30  	"testing"
    31  
    32  	"github.com/nebulasio/go-nebulas/nr"
    33  
    34  	"github.com/nebulasio/go-nebulas/account"
    35  	"github.com/nebulasio/go-nebulas/consensus/dpos"
    36  
    37  	"github.com/nebulasio/go-nebulas/core"
    38  	"github.com/nebulasio/go-nebulas/core/pb"
    39  	"github.com/nebulasio/go-nebulas/core/state"
    40  	"github.com/nebulasio/go-nebulas/crypto"
    41  	"github.com/nebulasio/go-nebulas/crypto/keystore"
    42  	"github.com/nebulasio/go-nebulas/crypto/keystore/secp256k1"
    43  	"github.com/nebulasio/go-nebulas/storage"
    44  	"github.com/nebulasio/go-nebulas/util"
    45  	"github.com/nebulasio/go-nebulas/util/byteutils"
    46  	"github.com/stretchr/testify/assert"
    47  	"github.com/stretchr/testify/require"
    48  )
    49  
    50  const contractStr = "n218MQSwc7hcXvM7rUkr6smMoiEf2VbGuYr"
    51  
    52  func newUint128FromIntWrapper(a int64) *util.Uint128 {
    53  	b, _ := util.NewUint128FromInt(a)
    54  	return b
    55  }
    56  
    57  type testNR struct {
    58  }
    59  
    60  func (r *testNR) GetNRListByHeight(height uint64) (core.Data, error) {
    61  	data := &nr.NRData{
    62  		Nrs: []*nr.NRItem{&nr.NRItem{
    63  			Address: "n1FkntVUMPAsESuCAAPK711omQk19JotBjM",
    64  			Score:   "10.09",
    65  		}},
    66  	}
    67  	return data, nil
    68  }
    69  
    70  func (r *testNR) GetNRSummary(height uint64) (core.Data, error) {
    71  	if height > 1000 {
    72  		sum := &nr.NRSummary{
    73  			StartHeight: 1,
    74  			EndHeight:   500,
    75  			Sum: &nr.NRSummaryData{
    76  				InOuts: "123123",
    77  				Score:  "100",
    78  			},
    79  		}
    80  		return sum, nil
    81  	}
    82  	return nil, nr.ErrNRSummaryNotFound
    83  }
    84  
    85  func (r *testNR) GetNRHandle(start, end, version uint64) (string, error) {
    86  	return "", nil
    87  }
    88  
    89  func (r *testNR) GetNRListByHandle(handle []byte) (core.Data, error) {
    90  	return nil, nil
    91  }
    92  
    93  type testBlock struct {
    94  	height uint64
    95  
    96  	nr core.NR
    97  }
    98  
    99  // Coinbase mock
   100  func (block *testBlock) Coinbase() *core.Address {
   101  	addr, _ := core.AddressParse("n1FkntVUMPAsESuCAAPK711omQk19JotBjM")
   102  	return addr
   103  }
   104  
   105  // Hash mock
   106  func (block *testBlock) Hash() byteutils.Hash {
   107  	return []byte("59fc526072b09af8a8ca9732dae17132c4e9127e43cf2232")
   108  }
   109  
   110  // Height mock
   111  func (block *testBlock) Height() uint64 {
   112  	return block.height
   113  }
   114  
   115  // RandomSeed mock
   116  func (block *testBlock) RandomSeed() string {
   117  	return "59fc526072b09af8a8ca9732dae17132c4e9127e43cf2232"
   118  }
   119  
   120  // RandomAvailable mock
   121  func (block *testBlock) RandomAvailable() bool {
   122  	return true
   123  }
   124  
   125  // DateAvailable
   126  func (block *testBlock) DateAvailable() bool {
   127  	return true
   128  }
   129  
   130  // GetTransaction mock
   131  func (block *testBlock) GetTransaction(hash byteutils.Hash) (*core.Transaction, error) {
   132  	return nil, nil
   133  }
   134  
   135  // RecordEvent mock
   136  func (block *testBlock) RecordEvent(txHash byteutils.Hash, topic, data string) error {
   137  	return nil
   138  }
   139  
   140  func (block *testBlock) Timestamp() int64 {
   141  	return int64(0)
   142  }
   143  
   144  func (block *testBlock) NR() core.NR {
   145  	return block.nr
   146  }
   147  
   148  func mockBlock() Block {
   149  	block := &testBlock{core.NebCompatibility.NvmMemoryLimitWithoutInjectHeight(), &testNR{}}
   150  	return block
   151  }
   152  
   153  func mockBlockForLib(height uint64) Block {
   154  	block := &testBlock{height, &testNR{}}
   155  	return block
   156  }
   157  
   158  func mockTransaction() *core.Transaction {
   159  	return mockNormalTransaction("n1FkntVUMPAsESuCAAPK711omQk19JotBjM", "n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR", "0")
   160  }
   161  
   162  const ContractName = "contract.js"
   163  
   164  func mockNormalTransaction(from, to, value string) *core.Transaction {
   165  
   166  	fromAddr, _ := core.AddressParse(from)
   167  	toAddr, _ := core.AddressParse(to)
   168  	payload, _ := core.NewBinaryPayload(nil).ToBytes()
   169  	gasPrice, _ := util.NewUint128FromString("1000000")
   170  	gasLimit, _ := util.NewUint128FromString("2000000")
   171  	v, _ := util.NewUint128FromString(value)
   172  	tx, _ := core.NewTransaction(1, fromAddr, toAddr, v, 1, core.TxPayloadBinaryType, payload, gasPrice, gasLimit)
   173  
   174  	priv1 := secp256k1.GeneratePrivateKey()
   175  	signature, _ := crypto.NewSignature(keystore.SECP256K1)
   176  	signature.InitSign(priv1)
   177  	tx.Sign(signature)
   178  	return tx
   179  }
   180  
   181  func TestRunScriptSource(t *testing.T) {
   182  	tests := []struct {
   183  		filepath       string
   184  		expectedErr    error
   185  		expectedResult string
   186  	}{
   187  		{"test/test_require.js", nil, "\"\""},
   188  		{"test/test_console.js", nil, "\"\""},
   189  		{"test/test_storage_handlers.js", nil, "\"\""},
   190  		{"test/test_storage_class.js", nil, "\"\""},
   191  		{"test/test_storage.js", nil, "\"\""},
   192  		{"test/test_eval.js", core.ErrExecutionFailed, "EvalError: Code generation from strings disallowed for this context"},
   193  		{"test/test_date.js", nil, "\"\""},
   194  		{"test/test_bignumber_random.js", core.ErrExecutionFailed, "Error: BigNumber.random is not allowed in nvm."},
   195  		{"test/test_random_enable.js", nil, "\"\""},
   196  		{"test/test_random_disable.js", core.ErrExecutionFailed, "Error: Math.random func is not allowed in nvm."},
   197  		{"test/test_random_seed.js", core.ErrExecutionFailed, "Error: input seed must be a string"},
   198  	}
   199  
   200  	for _, tt := range tests {
   201  		t.Run(tt.filepath, func(t *testing.T) {
   202  			data, err := ioutil.ReadFile(tt.filepath)
   203  			assert.Nil(t, err, "filepath read error")
   204  
   205  			mem, _ := storage.NewMemoryStorage()
   206  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   207  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   208  			assert.Nil(t, err)
   209  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
   210  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   211  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   212  
   213  			engine := NewV8Engine(ctx)
   214  			engine.SetExecutionLimits(900000, 10000000)
   215  			result, err := engine.RunScriptSource(string(data), 0)
   216  			assert.Equal(t, tt.expectedErr, err)
   217  			assert.Equal(t, tt.expectedResult, result)
   218  			engine.Dispose()
   219  		})
   220  	}
   221  }
   222  
   223  func TestRunScriptSourceInModule(t *testing.T) {
   224  	tests := []struct {
   225  		filepath    string
   226  		sourceType  string
   227  		expectedErr error
   228  	}{
   229  		{"./test/test_require.js", "js", nil},
   230  		{"./test/test_setTimeout.js", "js", core.ErrExecutionFailed},
   231  		{"./test/test_console.js", "js", nil},
   232  		{"./test/test_storage_handlers.js", "js", nil},
   233  		{"./test/test_storage_class.js", "js", nil},
   234  		{"./test/test_storage.js", "js", nil},
   235  		{"./test/test_ERC20.js", "js", nil},
   236  		{"./test/test_eval.js", "js", core.ErrExecutionFailed},
   237  	}
   238  
   239  	for _, tt := range tests {
   240  		t.Run(tt.filepath, func(t *testing.T) {
   241  			data, err := ioutil.ReadFile(tt.filepath)
   242  			assert.Nil(t, err, "filepath read error")
   243  
   244  			mem, _ := storage.NewMemoryStorage()
   245  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   246  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   247  			assert.Nil(t, err)
   248  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
   249  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   250  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   251  
   252  			engine := NewV8Engine(ctx)
   253  			engine.SetExecutionLimits(100000, 10000000)
   254  			engine.AddModule(ContractName, string(data), 0)
   255  			runnableSource := fmt.Sprintf("require(\"%s\");", ContractName)
   256  			_, err = engine.RunScriptSource(runnableSource, 0)
   257  
   258  			assert.Equal(t, tt.expectedErr, err)
   259  			engine.Dispose()
   260  		})
   261  	}
   262  }
   263  
   264  func TestRunScriptSourceWithLimits(t *testing.T) {
   265  	tests := []struct {
   266  		name                          string
   267  		filepath                      string
   268  		limitsOfExecutionInstructions uint64
   269  		limitsOfTotalMemorySize       uint64
   270  		expectedErr                   error
   271  	}{
   272  		{"1", "test/test_oom_1.js", 100000, 0, ErrInsufficientGas},
   273  		{"2", "test/test_oom_1.js", 0, 500000, ErrExceedMemoryLimits},
   274  		{"3", "test/test_oom_1.js", 1000000, 50000000, ErrInsufficientGas},
   275  		{"4", "test/test_oom_1.js", 5000000, 70000, ErrExceedMemoryLimits},
   276  
   277  		{"5", "test/test_oom_2.js", 100000, 0, ErrInsufficientGas},
   278  		{"6", "test/test_oom_2.js", 0, 80000, ErrExceedMemoryLimits},
   279  		{"7", "test/test_oom_2.js", 10000000, 10000000, ErrInsufficientGas},
   280  		{"8", "test/test_oom_2.js", 10000000, 70000, ErrExceedMemoryLimits},
   281  	}
   282  
   283  	for _, tt := range tests {
   284  		t.Run(tt.name, func(t *testing.T) {
   285  			data, err := ioutil.ReadFile(tt.filepath)
   286  			assert.Nil(t, err, "filepath read error")
   287  
   288  			mem, _ := storage.NewMemoryStorage()
   289  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   290  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   291  			assert.Nil(t, err)
   292  			owner.AddBalance(newUint128FromIntWrapper(100000))
   293  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   294  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   295  
   296  			// direct run.
   297  			(func() {
   298  				engine := NewV8Engine(ctx)
   299  				engine.SetExecutionLimits(tt.limitsOfExecutionInstructions, tt.limitsOfTotalMemorySize)
   300  				source, _, _ := engine.InjectTracingInstructions(string(data))
   301  				_, err = engine.RunScriptSource(source, 0)
   302  				fmt.Printf("err:%v\n", err)
   303  				assert.Equal(t, tt.expectedErr, err)
   304  				engine.Dispose()
   305  			})()
   306  
   307  			// modularized run.
   308  			(func() {
   309  				moduleID := fmt.Sprintf("%s", ContractName)
   310  				runnableSource := fmt.Sprintf("require(\"%s\");", moduleID)
   311  
   312  				engine := NewV8Engine(ctx)
   313  				engine.SetExecutionLimits(tt.limitsOfExecutionInstructions, tt.limitsOfTotalMemorySize)
   314  				engine.AddModule(ContractName, string(data), 0)
   315  				_, err = engine.RunScriptSource(runnableSource, 0)
   316  				assert.Equal(t, tt.expectedErr, err)
   317  				engine.Dispose()
   318  			})()
   319  		})
   320  	}
   321  }
   322  
   323  func TestRunScriptSourceMemConsistency(t *testing.T) {
   324  	tests := []struct {
   325  		name                          string
   326  		filepath                      string
   327  		limitsOfExecutionInstructions uint64
   328  		limitsOfTotalMemorySize       uint64
   329  		expectedMem                   uint64
   330  	}{
   331  		{"3", "test/test_oom_3.js", 1000000000, 5000000000, 0},
   332  	}
   333  
   334  	for _, tt := range tests {
   335  		t.Run(tt.name, func(t *testing.T) {
   336  			data, err := ioutil.ReadFile(tt.filepath)
   337  			assert.Nil(t, err, "filepath read error")
   338  
   339  			mem, _ := storage.NewMemoryStorage()
   340  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   341  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   342  			assert.Nil(t, err)
   343  			owner.AddBalance(newUint128FromIntWrapper(100000))
   344  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   345  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   346  
   347  			// direct run.
   348  			(func() {
   349  				engine := NewV8Engine(ctx)
   350  				engine.SetExecutionLimits(tt.limitsOfExecutionInstructions, tt.limitsOfTotalMemorySize)
   351  				source, _, _ := engine.InjectTracingInstructions(string(data))
   352  				_, err = engine.RunScriptSource(source, 0)
   353  				// assert.Equal(t, tt.expectedErr, err)
   354  				assert.Nil(t, err)
   355  				engine.Dispose()
   356  			})()
   357  
   358  			// modularized run.
   359  			(func() {
   360  				moduleID := fmt.Sprintf("%s", ContractName)
   361  				runnableSource := fmt.Sprintf("require(\"%s\");", moduleID)
   362  
   363  				engine := NewV8Engine(ctx)
   364  				engine.SetExecutionLimits(tt.limitsOfExecutionInstructions, tt.limitsOfTotalMemorySize)
   365  				engine.AddModule(ContractName, string(data), 0)
   366  				_, err = engine.RunScriptSource(runnableSource, 0)
   367  				// assert.Equal(t, tt.expectedErr, err)
   368  				assert.Nil(t, err)
   369  				engine.CollectTracingStats()
   370  				// fmt.Printf("total:%v", engine.actualTotalMemorySize)
   371  				assert.Equal(t, uint64(6703104), engine.actualTotalMemorySize)
   372  				engine.Dispose()
   373  			})()
   374  		})
   375  	}
   376  }
   377  
   378  func TestV8ResourceLimit(t *testing.T) {
   379  	tests := []struct {
   380  		name          string
   381  		contractPath  string
   382  		sourceType    string
   383  		initArgs      string
   384  		callArgs      string
   385  		initExceptErr string
   386  		callExceptErr string
   387  	}{
   388  		{"deploy test_oom_4.js", "./test/test_oom_4.js", "js", "[31457280]", "[31457280]", "", ""},
   389  		{"deploy test_oom_4.js", "./test/test_oom_4.js", "js", "[37748736]", "[37748736]", "", ""},
   390  		{"deploy test_oom_4.js", "./test/test_oom_4.js", "js", "[41943039]", "[41943039]", "exceed memory limits", "exceed memory limits"},
   391  	}
   392  
   393  	for _, tt := range tests {
   394  		t.Run(tt.name, func(t *testing.T) {
   395  			data, err := ioutil.ReadFile(tt.contractPath)
   396  			assert.Nil(t, err, "contract path read error")
   397  
   398  			mem, _ := storage.NewMemoryStorage()
   399  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   400  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   401  			assert.Nil(t, err)
   402  			owner.AddBalance(newUint128FromIntWrapper(10000000))
   403  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   404  
   405  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   406  			engine := NewV8Engine(ctx)
   407  			engine.SetExecutionLimits(10000, 10000000)
   408  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
   409  			engine.CollectTracingStats()
   410  			fmt.Printf("total:%v", engine.actualTotalMemorySize)
   411  			// assert.Nil(t, err)
   412  			if err != nil {
   413  				fmt.Printf("err:%v", err.Error())
   414  				assert.Equal(t, tt.initExceptErr, err.Error())
   415  			} else {
   416  				assert.Equal(t, tt.initExceptErr, "")
   417  			}
   418  			// assert.Equal(t, tt.initExceptErr, err.Error)
   419  
   420  			engine.Dispose()
   421  
   422  			engine = NewV8Engine(ctx)
   423  			engine.SetExecutionLimits(10000, 10000000)
   424  			_, err = engine.Call(string(data), tt.sourceType, "newMem", tt.callArgs)
   425  			// assert.Nil(t, err)
   426  			// assert.Equal(t, tt.initExceptErr, err.Error)
   427  			if err != nil {
   428  				assert.Equal(t, tt.initExceptErr, err.Error())
   429  			} else {
   430  				assert.Equal(t, tt.initExceptErr, "")
   431  			}
   432  			engine.Dispose()
   433  
   434  		})
   435  	}
   436  }
   437  func TestRunScriptSourceTimeout(t *testing.T) {
   438  	core.NebCompatibility = core.NewCompatibilityLocal()
   439  	tests := []struct {
   440  		filepath    string
   441  		height      uint64
   442  		expectedErr error
   443  	}{
   444  		{"test/test_infinite_loop.js", 1, ErrExecutionTimeout},
   445  		{"test/test_infinite_loop.js", 2, core.ErrUnexpected},
   446  	}
   447  
   448  	for _, tt := range tests {
   449  		t.Run(tt.filepath, func(t *testing.T) {
   450  			data, err := ioutil.ReadFile(tt.filepath)
   451  			assert.Nil(t, err, "filepath read error")
   452  
   453  			mem, _ := storage.NewMemoryStorage()
   454  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   455  
   456  			// owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   457  			// assert.Nil(t, err)
   458  
   459  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   460  			ctx, err := NewContext(mockBlockForLib(tt.height), mockTransaction(), contract, context)
   461  
   462  			// direct run.
   463  			(func() {
   464  				engine := NewV8Engine(ctx)
   465  				_, err = engine.RunScriptSource(string(data), 0)
   466  				assert.Equal(t, tt.expectedErr, err)
   467  				engine.Dispose()
   468  			})()
   469  
   470  			// modularized run.
   471  			(func() {
   472  				moduleID := fmt.Sprintf("%s", ContractName)
   473  				runnableSource := fmt.Sprintf("require(\"%s\");", moduleID)
   474  
   475  				engine := NewV8Engine(ctx)
   476  				engine.AddModule(moduleID, string(data), 0)
   477  				_, err = engine.RunScriptSource(runnableSource, 0)
   478  				assert.Equal(t, tt.expectedErr, err)
   479  				engine.Dispose()
   480  			})()
   481  		})
   482  	}
   483  }
   484  
   485  func TestDeployAndInitAndCall(t *testing.T) {
   486  	tests := []struct {
   487  		name         string
   488  		contractPath string
   489  		sourceType   string
   490  		initArgs     string
   491  		verifyArgs   string
   492  	}{
   493  		{"deploy sample_contract.js", "./test/sample_contract.js", "js", "[\"TEST001\", 123,[{\"name\":\"robin\",\"count\":2},{\"name\":\"roy\",\"count\":3},{\"name\":\"leon\",\"count\":4}]]", "[\"TEST001\", 123,[{\"name\":\"robin\",\"count\":2},{\"name\":\"roy\",\"count\":3},{\"name\":\"leon\",\"count\":4}]]"},
   494  	}
   495  
   496  	for _, tt := range tests {
   497  		t.Run(tt.name, func(t *testing.T) {
   498  			data, err := ioutil.ReadFile(tt.contractPath)
   499  			assert.Nil(t, err, "contract path read error")
   500  
   501  			mem, _ := storage.NewMemoryStorage()
   502  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   503  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   504  			assert.Nil(t, err)
   505  			owner.AddBalance(newUint128FromIntWrapper(10000000))
   506  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   507  
   508  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   509  			engine := NewV8Engine(ctx)
   510  			engine.SetExecutionLimits(10000, 10000000)
   511  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
   512  			assert.Nil(t, err)
   513  			engine.Dispose()
   514  
   515  			engine = NewV8Engine(ctx)
   516  			engine.SetExecutionLimits(10000, 10000000)
   517  			_, err = engine.Call(string(data), tt.sourceType, "dump", "")
   518  			assert.Nil(t, err)
   519  			engine.Dispose()
   520  
   521  			engine = NewV8Engine(ctx)
   522  			engine.SetExecutionLimits(10000, 10000000)
   523  			_, err = engine.Call(string(data), tt.sourceType, "verify", tt.verifyArgs)
   524  			assert.Nil(t, err)
   525  			engine.Dispose()
   526  
   527  			// force error.
   528  			mem, _ = storage.NewMemoryStorage()
   529  			context, _ = state.NewWorldState(dpos.NewDpos(), mem)
   530  			owner, err = context.GetOrCreateUserAccount([]byte("account1"))
   531  			assert.Nil(t, err)
   532  			contract, err = context.CreateContractAccount([]byte("account2"), nil, nil)
   533  			assert.Nil(t, err)
   534  
   535  			ctx, err = NewContext(mockBlock(), mockTransaction(), contract, context)
   536  			engine = NewV8Engine(ctx)
   537  			engine.SetExecutionLimits(10000, 10000000)
   538  			_, err = engine.Call(string(data), tt.sourceType, "verify", tt.verifyArgs)
   539  			assert.NotNil(t, err)
   540  			engine.Dispose()
   541  		})
   542  	}
   543  }
   544  
   545  func TestContracts(t *testing.T) {
   546  	type fields struct {
   547  		function string
   548  		args     string
   549  	}
   550  	tests := []struct {
   551  		contract   string
   552  		sourceType string
   553  		initArgs   string
   554  		calls      []fields
   555  	}{
   556  		{
   557  			"./test/contract_rectangle.js",
   558  			"js",
   559  			"[\"1024\", \"768\"]",
   560  			[]fields{
   561  				{"calcArea", "[]"},
   562  				{"verify", "[\"786432\"]"},
   563  			},
   564  		},
   565  		{
   566  			"./test/contract_rectangle.js",
   567  			"js",
   568  			"[\"999\", \"123\"]",
   569  			[]fields{
   570  				{"calcArea", "[]"},
   571  				{"verify", "[\"122877\"]"},
   572  			},
   573  		},
   574  	}
   575  
   576  	for _, tt := range tests {
   577  		t.Run(tt.contract, func(t *testing.T) {
   578  			data, err := ioutil.ReadFile(tt.contract)
   579  			assert.Nil(t, err, "contract path read error")
   580  
   581  			mem, _ := storage.NewMemoryStorage()
   582  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   583  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   584  			assert.Nil(t, err)
   585  			owner.AddBalance(newUint128FromIntWrapper(10000000))
   586  			contract, err := context.CreateContractAccount([]byte("account2"), nil, nil)
   587  			assert.Nil(t, err)
   588  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   589  
   590  			// deploy and init.
   591  			engine := NewV8Engine(ctx)
   592  			engine.SetExecutionLimits(1000, 10000000)
   593  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
   594  			assert.Nil(t, err)
   595  			engine.Dispose()
   596  
   597  			// call.
   598  			for _, fields := range tt.calls {
   599  				engine = NewV8Engine(ctx)
   600  				engine.SetExecutionLimits(1000, 10000000)
   601  				_, err = engine.Call(string(data), tt.sourceType, fields.function, fields.args)
   602  				assert.Nil(t, err)
   603  				engine.Dispose()
   604  			}
   605  		})
   606  	}
   607  }
   608  
   609  func TestFunctionNameCheck(t *testing.T) {
   610  	tests := []struct {
   611  		function    string
   612  		expectedErr error
   613  		args        string
   614  	}{
   615  		{"$dump", nil, ""},
   616  		{"dump", nil, ""},
   617  		{"dump_1", nil, ""},
   618  		{"init", ErrDisallowCallPrivateFunction, ""},
   619  		{"Init", ErrDisallowCallPrivateFunction, ""},
   620  		{"9dump", ErrDisallowCallNotStandardFunction, ""},
   621  		{"_dump", ErrDisallowCallNotStandardFunction, ""},
   622  	}
   623  
   624  	for _, tt := range tests {
   625  		t.Run(tt.function, func(t *testing.T) {
   626  			data, err := ioutil.ReadFile("test/sample_contract.js")
   627  			sourceType := "js"
   628  			assert.Nil(t, err, "contract path read error")
   629  
   630  			mem, _ := storage.NewMemoryStorage()
   631  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   632  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   633  			assert.Nil(t, err)
   634  			owner.AddBalance(newUint128FromIntWrapper(1000000))
   635  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   636  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   637  
   638  			engine := NewV8Engine(ctx)
   639  			engine.SetExecutionLimits(1000, 10000000)
   640  			_, err = engine.Call(string(data), sourceType, tt.function, tt.args)
   641  			assert.Equal(t, tt.expectedErr, err)
   642  			engine.Dispose()
   643  		})
   644  	}
   645  }
   646  func TestMultiEngine(t *testing.T) {
   647  	mem, _ := storage.NewMemoryStorage()
   648  	context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   649  	owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   650  	assert.Nil(t, err)
   651  	owner.AddBalance(newUint128FromIntWrapper(1000000))
   652  	contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
   653  
   654  	var wg sync.WaitGroup
   655  	for i := 0; i < 100; i++ {
   656  		wg.Add(1)
   657  		go func() {
   658  			defer wg.Done()
   659  
   660  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   661  
   662  			engine := NewV8Engine(ctx)
   663  			engine.SetExecutionLimits(1000, 10000000)
   664  			defer engine.Dispose()
   665  
   666  			_, err = engine.RunScriptSource("console.log('running.');", 0)
   667  			assert.Nil(t, err)
   668  		}()
   669  	}
   670  	wg.Wait()
   671  }
   672  
   673  func TestInstructionCounter1_1_0TestSuite(t *testing.T) {
   674  	core.NebCompatibility = core.NewCompatibilityLocal()
   675  	tests := []struct {
   676  		filepath                                string
   677  		strictDisallowUsageOfInstructionCounter int
   678  		expectedErr                             error
   679  		expectedResult                          string
   680  	}{
   681  		{"./test/instruction_counter_tests/redefine1.js", 1, ErrInjectTracingInstructionFailed, ""},
   682  		{"./test/instruction_counter_tests/redefine2.js", 1, ErrInjectTracingInstructionFailed, ""},
   683  		{"./test/instruction_counter_tests/redefine3.js", 1, ErrInjectTracingInstructionFailed, ""},
   684  		{"./test/instruction_counter_tests/redefine4.js", 1, ErrInjectTracingInstructionFailed, ""},
   685  		{"./test/instruction_counter_tests/redefine5.js", 1, ErrInjectTracingInstructionFailed, ""},
   686  		{"./test/instruction_counter_tests/redefine6.js", 1, ErrInjectTracingInstructionFailed, ""},
   687  		{"./test/instruction_counter_tests/redefine7.js", 1, ErrInjectTracingInstructionFailed, ""},
   688  		{"./test/instruction_counter_tests/function.js", 1, ErrInjectTracingInstructionFailed, ""},
   689  		{"./test/instruction_counter_tests/redefine1.js", 0, ErrInjectTracingInstructionFailed, ""},
   690  		{"./test/instruction_counter_tests/redefine2.js", 0, ErrInjectTracingInstructionFailed, ""},
   691  		{"./test/instruction_counter_tests/redefine3.js", 0, ErrInjectTracingInstructionFailed, ""},
   692  		{"./test/instruction_counter_tests/redefine4.js", 0, core.ErrExecutionFailed, "Error: still not break the jail of _instruction_counter."},
   693  		{"./test/instruction_counter_tests/redefine5.js", 0, ErrInjectTracingInstructionFailed, ""},
   694  		{"./test/instruction_counter_tests/redefine6.js", 0, nil, "\"\""},
   695  		{"./test/instruction_counter_tests/redefine7.js", 0, nil, "\"\""},
   696  		{"./test/instruction_counter_tests/function.js", 0, nil, "\"\""},
   697  		{"./test/instruction_counter_tests/if.js", 0, nil, "\"\""},
   698  		{"./test/instruction_counter_tests/switch.js", 0, nil, "\"\""},
   699  		{"./test/instruction_counter_tests/for.js", 0, nil, "\"\""},
   700  		{"./test/instruction_counter_tests/with.js", 0, nil, "\"\""},
   701  		{"./test/instruction_counter_tests/while.js", 0, nil, "\"\""},
   702  		{"./test/instruction_counter_tests/throw.js", 0, nil, "\"\""},
   703  		{"./test/instruction_counter_tests/switch.js", 0, nil, "\"\""},
   704  		{"./test/instruction_counter_tests/condition_operator.js", 0, nil, "\"\""},
   705  		{"./test/instruction_counter_tests/storage_usage.js", 0, nil, "\"\""},
   706  		{"./test/instruction_counter_tests/event_usage.js", 0, nil, "\"\""},
   707  		{"./test/instruction_counter_tests/blockchain_usage.js", 0, nil, "\"\""},
   708  	}
   709  
   710  	for _, tt := range tests {
   711  		t.Run(tt.filepath, func(t *testing.T) {
   712  			data, err := ioutil.ReadFile(tt.filepath)
   713  			assert.Nil(t, err, "filepath read error")
   714  
   715  			mem, _ := storage.NewMemoryStorage()
   716  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   717  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   718  			assert.Nil(t, err)
   719  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
   720  			addr, err := core.NewContractAddressFromData([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"), byteutils.FromUint64(1))
   721  			assert.Nil(t, err)
   722  			contract, err := context.CreateContractAccount(addr.Bytes(), nil, &corepb.ContractMeta{Version: "1.1.0"})
   723  			assert.Nil(t, err)
   724  			ctx, err := NewContext(mockBlockForLib(3), mockTransaction(), contract, context)
   725  
   726  			moduleID := ContractName
   727  			runnableSource := fmt.Sprintf("var x = require(\"%s\");", moduleID)
   728  
   729  			engine := NewV8Engine(ctx)
   730  			engine.strictDisallowUsageOfInstructionCounter = tt.strictDisallowUsageOfInstructionCounter
   731  			engine.enableLimits = true
   732  			err = engine.AddModule(moduleID, string(data), 0)
   733  			if err != nil {
   734  				assert.Equal(t, tt.expectedErr, err)
   735  			} else {
   736  				result, err := engine.RunScriptSource(runnableSource, 0)
   737  				assert.Equal(t, tt.expectedErr, err)
   738  				assert.Equal(t, tt.expectedResult, result)
   739  			}
   740  			engine.Dispose()
   741  		})
   742  	}
   743  }
   744  func TestCounter1_0_0TestSuite(t *testing.T) {
   745  	core.NebCompatibility = core.NewCompatibilityTestNet()
   746  	ClearSourceModuleCache()
   747  	tests := []struct {
   748  		filepath                                string
   749  		strictDisallowUsageOfInstructionCounter int
   750  		expectedErr                             error
   751  		expectedResult                          string
   752  	}{
   753  		{"./test/instruction_counter_tests/redefine1.js", 1, ErrInjectTracingInstructionFailed, ""},
   754  		{"./test/instruction_counter_tests/redefine2.js", 1, ErrInjectTracingInstructionFailed, ""},
   755  		{"./test/instruction_counter_tests/redefine3.js", 1, ErrInjectTracingInstructionFailed, ""},
   756  		{"./test/instruction_counter_tests/redefine4.js", 1, ErrInjectTracingInstructionFailed, ""},
   757  		{"./test/instruction_counter_tests/redefine5.js", 1, ErrInjectTracingInstructionFailed, ""},
   758  		{"./test/instruction_counter_tests/redefine6.js", 1, ErrInjectTracingInstructionFailed, ""},
   759  		{"./test/instruction_counter_tests/redefine7.js", 1, ErrInjectTracingInstructionFailed, ""},
   760  		{"./test/instruction_counter_tests/function.js", 1, ErrInjectTracingInstructionFailed, ""},
   761  		{"./test/instruction_counter_tests/redefine1.js", 0, ErrInjectTracingInstructionFailed, ""},
   762  		{"./test/instruction_counter_tests/redefine2.js", 0, ErrInjectTracingInstructionFailed, ""},
   763  		{"./test/instruction_counter_tests/redefine3.js", 0, ErrInjectTracingInstructionFailed, ""},
   764  		{"./test/instruction_counter_tests/redefine4.js", 0, core.ErrExecutionFailed, "Error: still not break the jail of _instruction_counter."},
   765  		{"./test/instruction_counter_tests/redefine5.js", 0, ErrInjectTracingInstructionFailed, ""},
   766  		{"./test/instruction_counter_tests/redefine6.js", 0, nil, "\"\""},
   767  		{"./test/instruction_counter_tests/redefine7.js", 0, nil, "\"\""},
   768  		{"./test/instruction_counter_tests/function.js", 0, nil, "\"\""},
   769  		{"./test/instruction_counter_tests/if.js", 0, nil, "\"\""},
   770  		{"./test/instruction_counter_tests/switch.js", 0, nil, "\"\""},
   771  		{"./test/instruction_counter_tests/for_1_0_0.js", 0, nil, "\"\""},
   772  		{"./test/instruction_counter_tests/with.js", 0, nil, "\"\""},
   773  		{"./test/instruction_counter_tests/while_1_0_0.js", 0, nil, "\"\""},
   774  		{"./test/instruction_counter_tests/throw.js", 0, nil, "\"\""},
   775  		{"./test/instruction_counter_tests/switch.js", 0, nil, "\"\""},
   776  		{"./test/instruction_counter_tests/condition_operator.js", 0, nil, "\"\""},
   777  		{"./test/instruction_counter_tests/storage_usage.js", 0, nil, "\"\""},
   778  		{"./test/instruction_counter_tests/event_usage.js", 0, nil, "\"\""},
   779  		{"./test/instruction_counter_tests/blockchain_usage.js", 0, nil, "\"\""},
   780  	}
   781  
   782  	for _, tt := range tests {
   783  		t.Run(tt.filepath, func(t *testing.T) {
   784  			data, err := ioutil.ReadFile(tt.filepath)
   785  			assert.Nil(t, err, "filepath read error")
   786  
   787  			mem, _ := storage.NewMemoryStorage()
   788  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   789  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   790  			assert.Nil(t, err)
   791  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
   792  			addr, err := core.NewContractAddressFromData([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"), byteutils.FromUint64(1))
   793  			assert.Nil(t, err)
   794  			contract, err := context.CreateContractAccount(addr.Bytes(), nil, nil)
   795  			assert.Nil(t, err)
   796  			ctx, err := NewContext(mockBlockForLib(1), mockTransaction(), contract, context)
   797  
   798  			moduleID := ContractName
   799  			runnableSource := fmt.Sprintf("var x = require(\"%s\");", moduleID)
   800  
   801  			engine := NewV8Engine(ctx)
   802  			engine.strictDisallowUsageOfInstructionCounter = tt.strictDisallowUsageOfInstructionCounter
   803  			engine.enableLimits = true
   804  			err = engine.AddModule(moduleID, string(data), 0)
   805  			if err != nil {
   806  				assert.Equal(t, tt.expectedErr, err)
   807  			} else {
   808  				result, err := engine.RunScriptSource(runnableSource, 0)
   809  				assert.Equal(t, tt.expectedErr, err)
   810  				assert.Equal(t, tt.expectedResult, result)
   811  			}
   812  			engine.Dispose()
   813  		})
   814  	}
   815  }
   816  
   817  func TestTypeScriptExecution(t *testing.T) {
   818  	core.NebCompatibility = core.NewCompatibilityLocal()
   819  	tests := []struct {
   820  		filepath    string
   821  		expectedErr error
   822  	}{
   823  		{"./test/test_greeter.ts", nil},
   824  	}
   825  
   826  	for _, tt := range tests {
   827  		t.Run(tt.filepath, func(t *testing.T) {
   828  			data, err := ioutil.ReadFile(tt.filepath)
   829  			assert.Nil(t, err, "filepath read error")
   830  
   831  			mem, _ := storage.NewMemoryStorage()
   832  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   833  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   834  			assert.Nil(t, err)
   835  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
   836  			contract, err := context.CreateContractAccount([]byte("account2"), nil, &corepb.ContractMeta{Version: "1.1.0"})
   837  			assert.Nil(t, err)
   838  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   839  
   840  			moduleID := ContractName
   841  			runnableSource := fmt.Sprintf("require(\"%s\");", moduleID)
   842  
   843  			engine := NewV8Engine(ctx)
   844  			defer engine.Dispose()
   845  
   846  			engine.enableLimits = true
   847  			jsSource, _, err := engine.TranspileTypeScript(string(data))
   848  			if err != nil {
   849  				assert.Equal(t, tt.expectedErr, err)
   850  				return
   851  			}
   852  
   853  			err = engine.AddModule(moduleID, string(jsSource), 0)
   854  			if err != nil {
   855  				assert.Equal(t, tt.expectedErr, err)
   856  			} else {
   857  				_, err := engine.RunScriptSource(runnableSource, 0)
   858  				assert.Equal(t, tt.expectedErr, err)
   859  			}
   860  		})
   861  	}
   862  }
   863  
   864  func DeprecatedTestRunMozillaJSTestSuite(t *testing.T) {
   865  	mem, _ := storage.NewMemoryStorage()
   866  	context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   867  	owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   868  	assert.Nil(t, err)
   869  	owner.AddBalance(newUint128FromIntWrapper(1000000000))
   870  
   871  	contract, err := context.CreateContractAccount([]byte("account2"), nil, nil)
   872  	assert.Nil(t, err)
   873  	ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   874  
   875  	var runTest func(dir string, shelljs string)
   876  	runTest = func(dir string, shelljs string) {
   877  		files, err := ioutil.ReadDir(dir)
   878  		require.Nil(t, err)
   879  
   880  		cwdShelljs := fmt.Sprintf("%s/shell.js", dir)
   881  		if _, err := os.Stat(cwdShelljs); !os.IsNotExist(err) {
   882  			shelljs = fmt.Sprintf("%s;%s", shelljs, cwdShelljs)
   883  		}
   884  
   885  		for _, file := range files {
   886  			filepath := fmt.Sprintf("%s/%s", dir, file.Name())
   887  			fi, err := os.Stat(filepath)
   888  			require.Nil(t, err)
   889  
   890  			if fi.IsDir() {
   891  				runTest(filepath, shelljs)
   892  				continue
   893  			}
   894  
   895  			if !strings.HasSuffix(file.Name(), ".js") {
   896  				continue
   897  			}
   898  			if strings.Compare(file.Name(), "browser.js") == 0 || strings.Compare(file.Name(), "shell.js") == 0 || strings.HasPrefix(file.Name(), "toLocale") {
   899  				continue
   900  			}
   901  
   902  			buf := bytes.NewBufferString("this.print = console.log;var native_eval = eval;eval = function (s) { try {  return native_eval(s); } catch (e) { return \"error\"; }};")
   903  
   904  			jsfiles := fmt.Sprintf("%s;%s;%s", shelljs, "test/mozilla_js_tests_loader.js", filepath)
   905  
   906  			for _, v := range strings.Split(jsfiles, ";") {
   907  				if len(v) == 0 {
   908  					continue
   909  				}
   910  
   911  				fi, err := os.Stat(v)
   912  				require.Nil(t, err)
   913  				f, err := os.Open(v)
   914  				require.Nil(t, err)
   915  				reader := bufio.NewReader(f)
   916  				buf.Grow(int(fi.Size()))
   917  				buf.ReadFrom(reader)
   918  			}
   919  			// execute.
   920  			engine := NewV8Engine(ctx)
   921  			engine.SetTestingFlag(true)
   922  			engine.enableLimits = true
   923  			_, err = engine.RunScriptSource(buf.String(), 0)
   924  			//t.Logf("ret:%v, err:%v", ret, err)
   925  			assert.Nil(t, err)
   926  		}
   927  	}
   928  
   929  	runTest("test/mozilla_js_tests", "")
   930  }
   931  
   932  func TestNebulasContract(t *testing.T) {
   933  	core.NebCompatibility = core.NewCompatibilityLocal()
   934  	tests := []struct {
   935  		name     string
   936  		value    string
   937  		function string
   938  		args     string
   939  		err      error
   940  	}{
   941  		{"1", "0", "unpayable", "", nil},
   942  		{"2", "0", "unpayable", "[1]", nil},
   943  		{"3", "1", "unpayable", "", nil},
   944  		{"4", "0", "payable", "", core.ErrExecutionFailed},
   945  		{"5", "1", "payable", "", nil},
   946  		{"6", "1", "payable", "[1]", nil},
   947  		{"7", "0", "contract1", "[1]", nil},
   948  		{"8", "1", "contract1", "[1]", nil},
   949  		{"9", "0", "contract2", "[1]", core.ErrExecutionFailed},
   950  		{"10", "1", "contract2", "[1]", core.ErrExecutionFailed},
   951  		{"11", "0", "contract3", "[1]", core.ErrExecutionFailed},
   952  		{"12", "1", "contract3", "[1]", nil},
   953  		{"13", "0", "contract4", "[1]", core.ErrExecutionFailed},
   954  		{"14", "1", "contract4", "[1]", core.ErrExecutionFailed},
   955  	}
   956  
   957  	mem, _ := storage.NewMemoryStorage()
   958  	context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   959  
   960  	addr, _ := core.NewAddressFromPublicKey([]byte{
   961  		2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7,
   962  		2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7,
   963  		2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 1, 2, 4, 5, 3})
   964  	owner, err := context.GetOrCreateUserAccount(addr.Bytes())
   965  	assert.Nil(t, err)
   966  	owner.AddBalance(newUint128FromIntWrapper(1000000000))
   967  
   968  	addr, _ = core.NewContractAddressFromData([]byte{1, 2, 3, 5, 7}, []byte{1, 2, 3, 5, 7})
   969  	contract, _ := context.CreateContractAccount(addr.Bytes(), nil, &corepb.ContractMeta{Version: "1.1.0"})
   970  
   971  	ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
   972  
   973  	data, err := ioutil.ReadFile("test/mixin.js")
   974  	assert.Nil(t, err, "filepath read error")
   975  	sourceType := "js"
   976  
   977  	for _, tt := range tests {
   978  		t.Run(tt.name, func(t *testing.T) {
   979  
   980  			ctx.tx = mockNormalTransaction("n1FkntVUMPAsESuCAAPK711omQk19JotBjM", "n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR", tt.value)
   981  			engine := NewV8Engine(ctx)
   982  			engine.SetExecutionLimits(10000, 100000000)
   983  			_, err := engine.Call(string(data), sourceType, tt.function, tt.args)
   984  			assert.Equal(t, tt.err, err)
   985  			engine.Dispose()
   986  		})
   987  	}
   988  }
   989  
   990  func TestThreadStackOverflow(t *testing.T) {
   991  	core.NebCompatibility = core.NewCompatibilityLocal()
   992  	tests := []struct {
   993  		filepath    string
   994  		expectedErr error
   995  	}{
   996  		{"test/test_stack_overflow.js", core.ErrExecutionFailed},
   997  	}
   998  	// lockx := sync.RWMutex{}
   999  
  1000  	for _, tt := range tests {
  1001  		t.Run(tt.filepath, func(t *testing.T) {
  1002  			data, err := ioutil.ReadFile(tt.filepath)
  1003  			assert.Nil(t, err, "filepath read error")
  1004  			for j := 0; j < 10; j++ {
  1005  
  1006  				var wg sync.WaitGroup
  1007  				for i := 0; i < 5; i++ {
  1008  					wg.Add(1)
  1009  					go func() {
  1010  						defer wg.Done()
  1011  
  1012  						mem, _ := storage.NewMemoryStorage()
  1013  						context, _ := state.NewWorldState(dpos.NewDpos(), mem)
  1014  						owner, err := context.GetOrCreateUserAccount([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"))
  1015  						assert.Nil(t, err)
  1016  						owner.AddBalance(newUint128FromIntWrapper(1000000000))
  1017  						contract, err := context.CreateContractAccount([]byte("n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"), nil, &corepb.ContractMeta{Version: "1.1.0"})
  1018  						assert.Nil(t, err)
  1019  
  1020  						ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
  1021  						engine := NewV8Engine(ctx)
  1022  						engine.SetExecutionLimits(100000000, 10000000)
  1023  						_, err = engine.DeployAndInit(string(data), "js", "")
  1024  						fmt.Printf("err:%v", err)
  1025  						// _, err = engine.RunScriptSource("", 0)
  1026  						assert.Equal(t, tt.expectedErr, err)
  1027  						engine.Dispose()
  1028  
  1029  					}()
  1030  					// }
  1031  				}
  1032  				wg.Wait()
  1033  			}
  1034  
  1035  		})
  1036  	}
  1037  }
  1038  func TestGetRandomBySingle(t *testing.T) {
  1039  	core.NebCompatibility = core.NewCompatibilityLocal()
  1040  	type TransferTest struct {
  1041  		to     string
  1042  		result bool
  1043  		value  string
  1044  	}
  1045  
  1046  	tests := []struct {
  1047  		test         string
  1048  		contractPath string
  1049  		sourceType   string
  1050  		name         string
  1051  		from         string
  1052  	}{
  1053  		{"getRandomBySingle", "./test/inner_call_tests/test_inner_transaction.js", "js", "getRandomSingle",
  1054  			"n1FkntVUMPAsESuCAAPK711omQk19JotBjM",
  1055  		},
  1056  	}
  1057  
  1058  	for _, tt := range tests {
  1059  		t.Run(tt.name, func(t *testing.T) {
  1060  			data, err := ioutil.ReadFile(tt.contractPath)
  1061  			assert.Nil(t, err, "contract path read error")
  1062  
  1063  			mem, _ := storage.NewMemoryStorage()
  1064  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
  1065  			owner, err := context.GetOrCreateUserAccount([]byte(tt.from))
  1066  			assert.Nil(t, err)
  1067  			owner.AddBalance(newUint128FromIntWrapper(10000000))
  1068  
  1069  			// prepare the contract.
  1070  			contractAddr, err := core.AddressParse(contractStr)
  1071  			contract, _ := context.CreateContractAccount(contractAddr.Bytes(), nil, &corepb.ContractMeta{Version: "1.1.0"})
  1072  			contract.AddBalance(newUint128FromIntWrapper(5))
  1073  
  1074  			// parepare env, block & transactions.
  1075  			tx := mockNormalTransaction(tt.from, "n1TV3sU6jyzR4rJ1D7jCAmtVGSntJagXZHC", "0")
  1076  			ctx, err := NewContext(mockBlock(), tx, contract, context)
  1077  
  1078  			// execute.
  1079  			engine := NewV8Engine(ctx)
  1080  			engine.SetExecutionLimits(10000, 100000000)
  1081  			args := fmt.Sprintf("[]")
  1082  			_, err = engine.DeployAndInit(string(data), tt.sourceType, args)
  1083  			assert.Nil(t, err)
  1084  			engine.Dispose()
  1085  
  1086  			// call name.
  1087  			engine = NewV8Engine(ctx)
  1088  			engine.SetExecutionLimits(10000, 100000000)
  1089  			rand, err := engine.Call(string(data), tt.sourceType, "getRandomSingle", "")
  1090  			fmt.Printf("rand:%v\n", rand)
  1091  			assert.Nil(t, err)
  1092  			// var nameStr string
  1093  			// err = json.Unmarshal([]byte(name), &nameStr)
  1094  			// assert.Nil(t, err)
  1095  			// assert.Equal(t, tt.name, nameStr)
  1096  			engine.Dispose()
  1097  
  1098  		})
  1099  	}
  1100  }
  1101  
  1102  func TestParallelBug(t *testing.T) {
  1103  	core.NebCompatibility = core.NewCompatibilityLocal()
  1104  	tests := []struct {
  1105  		name      string
  1106  		contracts []contract
  1107  		calls     []call
  1108  	}{
  1109  		{
  1110  			"deploy test_require_module.js",
  1111  			[]contract{
  1112  				contract{
  1113  					"test/test_parallel_bug.js",
  1114  					"js",
  1115  					"[1]",
  1116  				},
  1117  				contract{
  1118  					"test/test_parallel_bug.js",
  1119  					"js",
  1120  					"[2]",
  1121  				},
  1122  				contract{
  1123  					"test/test_parallel_bug.js",
  1124  					"js",
  1125  					"[3]",
  1126  				},
  1127  				contract{
  1128  					"test/test_parallel_bug.js",
  1129  					"js",
  1130  					"[4]",
  1131  				},
  1132  			},
  1133  			[]call{
  1134  				call{
  1135  					"test",
  1136  					"[]",
  1137  					[]string{"1"},
  1138  				},
  1139  			},
  1140  		},
  1141  	}
  1142  	tt := tests[0]
  1143  	for _, call := range tt.calls {
  1144  
  1145  		neb := mockNeb(t)
  1146  		manager, err := account.NewManager(neb)
  1147  		assert.Nil(t, err)
  1148  
  1149  		addrs := unlockAccount(t, neb)
  1150  		from := addrs[0]
  1151  
  1152  		// mint height 2, inner contracts >= 3
  1153  		mintBlock(t, neb, nil)
  1154  
  1155  		txs := []*core.Transaction{}
  1156  		contractsAddr := []string{}
  1157  
  1158  		// t.Run(tt.name, func(t *testing.T) {
  1159  		var nonce uint64 = 0
  1160  		for i := 0; i < 8; i++ {
  1161  			for _, v := range tt.contracts {
  1162  				nonce = nonce + 1
  1163  				data, err := ioutil.ReadFile(v.contractPath)
  1164  				assert.Nil(t, err, "contract path read error")
  1165  				source := string(data)
  1166  				sourceType := "js"
  1167  				argsDeploy := v.initArgs
  1168  				deploy, _ := core.NewDeployPayload(source, sourceType, argsDeploy)
  1169  				payloadDeploy, _ := deploy.ToBytes()
  1170  
  1171  				value, _ := util.NewUint128FromInt(0)
  1172  				gasLimit, _ := util.NewUint128FromInt(200000)
  1173  				txDeploy, err := core.NewTransaction(neb.BlockChain().ChainID(), from, from, value, nonce, core.TxPayloadDeployType, payloadDeploy, core.TransactionGasPrice, gasLimit)
  1174  				assert.Nil(t, err)
  1175  				assert.Nil(t, manager.SignTransaction(from, txDeploy))
  1176  				txs = append(txs, txDeploy)
  1177  
  1178  				contractAddr, err := txDeploy.GenerateContractAddress()
  1179  				assert.Nil(t, err)
  1180  				contractsAddr = append(contractsAddr, contractAddr.String())
  1181  			}
  1182  		}
  1183  		// })
  1184  
  1185  		// mint for contract deploy
  1186  		mintBlockWithDuration(t, neb, txs, 2)
  1187  
  1188  		for _, v := range contractsAddr {
  1189  			contract, err := core.AddressParse(v)
  1190  			assert.Nil(t, err)
  1191  			_, err = neb.BlockChain().TailBlock().CheckContract(contract)
  1192  			assert.Nil(t, err)
  1193  		}
  1194  
  1195  		// Contract1 := contractsAddr[1]
  1196  		// Contract2 := contractsAddr[2]
  1197  		callPayload, _ := core.NewCallPayload(call.function, "[]")
  1198  		payloadCall, _ := callPayload.ToBytes()
  1199  
  1200  		value, _ := util.NewUint128FromInt(6)
  1201  		gasLimit, _ := util.NewUint128FromInt(200000)
  1202  
  1203  		callTxs := []*core.Transaction{}
  1204  		for i := 0; i < 4; i++ {
  1205  			ContractAddr1, err := core.AddressParse(contractsAddr[0+i*8])
  1206  			txCall1, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[1], ContractAddr1, value,
  1207  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1208  			callTxs = append(callTxs, txCall1)
  1209  			assert.Nil(t, err)
  1210  			assert.Nil(t, manager.SignTransaction(txCall1.From(), txCall1))
  1211  
  1212  			ContractAddr2, err := core.AddressParse(contractsAddr[1+i*8])
  1213  			from = addrs[2]
  1214  			txCall2, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[2], ContractAddr2, value,
  1215  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1216  			callTxs = append(callTxs, txCall2)
  1217  			assert.Nil(t, err)
  1218  			assert.Nil(t, manager.SignTransaction(txCall2.From(), txCall2))
  1219  
  1220  			ContractAddr3, err := core.AddressParse(contractsAddr[2+i*8])
  1221  			txCall3, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[3], ContractAddr3, value,
  1222  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1223  			callTxs = append(callTxs, txCall3)
  1224  			assert.Nil(t, err)
  1225  			assert.Nil(t, manager.SignTransaction(txCall3.From(), txCall3))
  1226  
  1227  			ContractAddr4, err := core.AddressParse(contractsAddr[3+i*8])
  1228  			txCall4, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[4], ContractAddr4, value,
  1229  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1230  			callTxs = append(callTxs, txCall4)
  1231  			assert.Nil(t, err)
  1232  			assert.Nil(t, manager.SignTransaction(txCall4.From(), txCall4))
  1233  
  1234  			ContractAddr5, err := core.AddressParse(contractsAddr[4+i*8])
  1235  			txCall5, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[5], ContractAddr5, value,
  1236  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1237  			callTxs = append(callTxs, txCall5)
  1238  			assert.Nil(t, err)
  1239  			assert.Nil(t, manager.SignTransaction(txCall5.From(), txCall5))
  1240  
  1241  			ContractAddr6, err := core.AddressParse(contractsAddr[5+i*8])
  1242  			txCall6, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[6], ContractAddr6, value,
  1243  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1244  			callTxs = append(callTxs, txCall6)
  1245  			assert.Nil(t, err)
  1246  			assert.Nil(t, manager.SignTransaction(txCall6.From(), txCall6))
  1247  
  1248  			ContractAddr7, err := core.AddressParse(contractsAddr[6+i*8])
  1249  			txCall7, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[7], ContractAddr7, value,
  1250  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1251  			callTxs = append(callTxs, txCall7)
  1252  			assert.Nil(t, err)
  1253  			assert.Nil(t, manager.SignTransaction(txCall7.From(), txCall7))
  1254  
  1255  			ContractAddr8, err := core.AddressParse(contractsAddr[7+i*8])
  1256  			txCall8, err := core.NewTransaction(neb.BlockChain().ChainID(), addrs[8], ContractAddr8, value,
  1257  				uint64(1+i), core.TxPayloadCallType, payloadCall, core.TransactionGasPrice, gasLimit)
  1258  			callTxs = append(callTxs, txCall8)
  1259  			assert.Nil(t, err)
  1260  			assert.Nil(t, manager.SignTransaction(txCall8.From(), txCall8))
  1261  		}
  1262  		core.PackedParallelNum = 8
  1263  
  1264  		// mint for contract call
  1265  		mintBlockWithDuration(t, neb, callTxs, 2)
  1266  
  1267  		// check
  1268  		tail := neb.BlockChain().TailBlock()
  1269  		for _, v := range callTxs {
  1270  			events, err := tail.FetchEvents(v.Hash())
  1271  			assert.Nil(t, err)
  1272  			for _, event := range events {
  1273  				txEvent := core.TransactionEvent{}
  1274  				err = json.Unmarshal([]byte(event.Data), &txEvent)
  1275  				assert.Nil(t, err)
  1276  				assert.Equal(t, txEvent.GasUsed, "20142")
  1277  				// fmt.Println("==============", event.Data)
  1278  			}
  1279  		}
  1280  	}
  1281  }
  1282  
  1283  func TestMultiLibVersion(t *testing.T) {
  1284  	tests := []struct {
  1285  		filepath       string
  1286  		expectedErr    error
  1287  		expectedResult string
  1288  	}{
  1289  		{"test/test_multi_lib_version_require.js", nil, "\"\""},
  1290  		{"test/test_uint.js", nil, "\"\""},
  1291  		{"test/test_date_1.0.5.js", nil, "\"\""},
  1292  		{"test/test_crypto.js", nil, "\"\""},
  1293  		{"test/test_blockchain_1.0.5.js", nil, "\"\""},
  1294  	}
  1295  
  1296  	for _, tt := range tests {
  1297  		t.Run(tt.filepath, func(t *testing.T) {
  1298  			data, err := ioutil.ReadFile(tt.filepath)
  1299  			assert.Nil(t, err, "filepath read error")
  1300  			mem, _ := storage.NewMemoryStorage()
  1301  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
  1302  			addr, _ := core.AddressParse("n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE")
  1303  			owner, err := context.GetOrCreateUserAccount(addr.Bytes())
  1304  			assert.Nil(t, err)
  1305  			owner.AddBalance(newUint128FromIntWrapper(1000000000000))
  1306  			addr, _ = core.AddressParse("n1p8cwrrfrbFe71eda1PQ6y4WnX3gp8bYze")
  1307  			contract, _ := context.CreateContractAccount(addr.Bytes(), nil, &corepb.ContractMeta{Version: "1.0.5"})
  1308  			ctx, err := NewContext(mockBlockForLib(2000000), mockTransaction(), contract, context)
  1309  
  1310  			engine := NewV8Engine(ctx)
  1311  			engine.SetExecutionLimits(5000000, 10000000)
  1312  			result, err := engine.RunScriptSource(string(data), 0)
  1313  			assert.Equal(t, tt.expectedErr, err)
  1314  			assert.Equal(t, tt.expectedResult, result)
  1315  			engine.Dispose()
  1316  		})
  1317  	}
  1318  }
  1319  
  1320  func TestNebulasRank(t *testing.T) {
  1321  	core.NebCompatibility = core.NewCompatibilityLocal()
  1322  	tests := []struct {
  1323  		name         string
  1324  		contractPath string
  1325  		function     string
  1326  		args         string
  1327  		expectedErr  error
  1328  		result       string
  1329  	}{
  1330  		{"case1", "./test/test_nebulas_rank.js", "rank", "[\"addr\"]", core.ErrExecutionFailed, "Address is invalid"},
  1331  		{"case2", "./test/test_nebulas_rank.js", "rank", "[\"n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE\"]", core.ErrExecutionFailed, "Failed to find nr value"},
  1332  		{"case3", "./test/test_nebulas_rank.js", "rank", "[\"n1FkntVUMPAsESuCAAPK711omQk19JotBjM\"]", nil, "\"10.09\""},
  1333  	}
  1334  
  1335  	for _, tt := range tests {
  1336  		t.Run(tt.name, func(t *testing.T) {
  1337  			data, err := ioutil.ReadFile(tt.contractPath)
  1338  			assert.Nil(t, err, "filepath read error")
  1339  
  1340  			mem, _ := storage.NewMemoryStorage()
  1341  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
  1342  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
  1343  			assert.Nil(t, err)
  1344  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
  1345  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, &corepb.ContractMeta{Version: "1.1.0"})
  1346  			ctx, err := NewContext(mockBlockForLib(2), mockTransaction(), contract, context)
  1347  
  1348  			engine := NewV8Engine(ctx)
  1349  			engine.SetExecutionLimits(900000, 10000000)
  1350  			result, err := engine.Call(string(data), "js", tt.function, tt.args)
  1351  			assert.Equal(t, tt.expectedErr, err)
  1352  			assert.Equal(t, tt.result, result)
  1353  			engine.Dispose()
  1354  		})
  1355  	}
  1356  }
  1357  
  1358  func TestNebulasRankSummary(t *testing.T) {
  1359  	core.NebCompatibility = core.NewCompatibilityLocal()
  1360  	tests := []struct {
  1361  		name         string
  1362  		contractPath string
  1363  		height       uint64
  1364  		function     string
  1365  		expectedErr  error
  1366  		result       string
  1367  	}{
  1368  		{"case1", "./test/test_nebulas_rank.js", 100, "summary", core.ErrExecutionFailed, "Failed to get nr summary"},
  1369  		{"case2", "./test/test_nebulas_rank.js", 1200, "summary", nil, "{\"start_height\":\"1\",\"end_height\":\"500\",\"version\":\"0\",\"sum\":{\"in_outs\":\"123123\",\"score\":\"100\"},\"err\":\"\"}"},
  1370  	}
  1371  
  1372  	for _, tt := range tests {
  1373  		t.Run(tt.name, func(t *testing.T) {
  1374  
  1375  			data, err := ioutil.ReadFile(tt.contractPath)
  1376  			assert.Nil(t, err, "filepath read error")
  1377  
  1378  			mem, _ := storage.NewMemoryStorage()
  1379  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
  1380  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
  1381  			assert.Nil(t, err)
  1382  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
  1383  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, &corepb.ContractMeta{Version: "1.1.0"})
  1384  			ctx, err := NewContext(mockBlockForLib(tt.height), mockTransaction(), contract, context)
  1385  
  1386  			engine := NewV8Engine(ctx)
  1387  			engine.SetExecutionLimits(900000, 10000000)
  1388  			result, err := engine.Call(string(data), "js", tt.function, "")
  1389  			assert.Equal(t, tt.expectedErr, err)
  1390  			assert.Equal(t, tt.result, result)
  1391  			engine.Dispose()
  1392  		})
  1393  	}
  1394  }