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 }