github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/execution/protocol_test.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package execution 7 8 import ( 9 "bytes" 10 "context" 11 "encoding/hex" 12 "encoding/json" 13 "fmt" 14 "io" 15 "math/big" 16 "os" 17 "testing" 18 "time" 19 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/core/types" 22 "github.com/mohae/deepcopy" 23 "github.com/pkg/errors" 24 "github.com/stretchr/testify/require" 25 "go.uber.org/zap" 26 27 "github.com/iotexproject/go-pkgs/crypto" 28 "github.com/iotexproject/go-pkgs/hash" 29 "github.com/iotexproject/iotex-address/address" 30 "github.com/iotexproject/iotex-proto/golang/iotextypes" 31 32 "github.com/iotexproject/iotex-core/action" 33 "github.com/iotexproject/iotex-core/action/protocol" 34 "github.com/iotexproject/iotex-core/action/protocol/account" 35 accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" 36 "github.com/iotexproject/iotex-core/action/protocol/execution/evm" 37 "github.com/iotexproject/iotex-core/action/protocol/rewarding" 38 "github.com/iotexproject/iotex-core/action/protocol/rolldpos" 39 "github.com/iotexproject/iotex-core/actpool" 40 "github.com/iotexproject/iotex-core/blockchain" 41 "github.com/iotexproject/iotex-core/blockchain/block" 42 "github.com/iotexproject/iotex-core/blockchain/blockdao" 43 "github.com/iotexproject/iotex-core/blockchain/filedao" 44 "github.com/iotexproject/iotex-core/blockchain/genesis" 45 "github.com/iotexproject/iotex-core/blockindex" 46 "github.com/iotexproject/iotex-core/config" 47 "github.com/iotexproject/iotex-core/db" 48 "github.com/iotexproject/iotex-core/pkg/log" 49 "github.com/iotexproject/iotex-core/pkg/unit" 50 "github.com/iotexproject/iotex-core/state/factory" 51 "github.com/iotexproject/iotex-core/test/identityset" 52 "github.com/iotexproject/iotex-core/testutil" 53 ) 54 55 type ( 56 // ExpectedBalance defines an account-balance pair 57 ExpectedBalance struct { 58 Account string `json:"account"` 59 RawBalance string `json:"rawBalance"` 60 } 61 62 ExpectedBlockInfo struct { 63 TxRootHash string `json:"txRootHash"` 64 StateRootHash string `json:"stateRootHash"` 65 ReceiptRootHash string `json:"receiptRootHash"` 66 } 67 68 // GenesisBlockHeight defines an genesis blockHeight 69 GenesisBlockHeight struct { 70 IsBering bool `json:"isBering"` 71 IsIceland bool `json:"isIceland"` 72 IsLondon bool `json:"isLondon"` 73 IsShanghai bool `json:"isShanghai"` 74 } 75 76 Log struct { 77 Topics []string `json:"topics"` 78 Data string `json:"data"` 79 } 80 81 AccessTuple struct { 82 Address string `json:"address"` 83 StorageKeys []string `json:"storageKeys"` 84 } 85 86 ExecutionConfig struct { 87 Comment string `json:"comment"` 88 ContractIndex int `json:"contractIndex"` 89 AppendContractAddress bool `json:"appendContractAddress"` 90 ContractIndexToAppend int `json:"contractIndexToAppend"` 91 ContractAddressToAppend string `json:"contractAddressToAppend"` 92 ReadOnly bool `json:"readOnly"` 93 RawPrivateKey string `json:"rawPrivateKey"` 94 RawByteCode string `json:"rawByteCode"` 95 RawAmount string `json:"rawAmount"` 96 RawGasLimit uint `json:"rawGasLimit"` 97 RawGasPrice string `json:"rawGasPrice"` 98 RawAccessList []AccessTuple `json:"rawAccessList"` 99 Failed bool `json:"failed"` 100 RawReturnValue string `json:"rawReturnValue"` 101 RawExpectedGasConsumed uint `json:"rawExpectedGasConsumed"` 102 ExpectedStatus uint64 `json:"expectedStatus"` 103 ExpectedBalances []ExpectedBalance `json:"expectedBalances"` 104 ExpectedLogs []Log `json:"expectedLogs"` 105 ExpectedErrorMsg string `json:"expectedErrorMsg"` 106 ExpectedBlockInfos ExpectedBlockInfo `json:"expectedBlockInfos"` 107 } 108 ) 109 110 var ( 111 fixedTime = time.Unix(genesis.Default.Timestamp, 0) 112 ) 113 114 func (eb *ExpectedBalance) Balance() *big.Int { 115 balance, ok := new(big.Int).SetString(eb.RawBalance, 10) 116 if !ok { 117 log.L().Panic("invalid balance", zap.String("balance", eb.RawBalance)) 118 } 119 return balance 120 } 121 122 func readCode(sr protocol.StateReader, addr []byte) ([]byte, error) { 123 var c protocol.SerializableBytes 124 account, err := accountutil.LoadAccountByHash160(sr, hash.BytesToHash160(addr)) 125 if err != nil { 126 return nil, err 127 } 128 _, err = sr.State(&c, protocol.NamespaceOption(evm.CodeKVNameSpace), protocol.KeyOption(account.CodeHash[:])) 129 130 return c[:], err 131 } 132 133 func (cfg *ExecutionConfig) PrivateKey() crypto.PrivateKey { 134 priKey, err := crypto.HexStringToPrivateKey(cfg.RawPrivateKey) 135 if err != nil { 136 log.L().Panic( 137 "invalid private key", 138 zap.String("privateKey", cfg.RawPrivateKey), 139 zap.Error(err), 140 ) 141 } 142 143 return priKey 144 } 145 146 func (cfg *ExecutionConfig) Executor() address.Address { 147 priKey := cfg.PrivateKey() 148 addr := priKey.PublicKey().Address() 149 if addr == nil { 150 log.L().Panic( 151 "invalid private key", 152 zap.String("privateKey", cfg.RawPrivateKey), 153 zap.Error(errors.New("failed to get address")), 154 ) 155 } 156 157 return addr 158 } 159 160 func (cfg *ExecutionConfig) ByteCode() []byte { 161 byteCode, err := hex.DecodeString(cfg.RawByteCode) 162 if err != nil { 163 log.L().Panic( 164 "invalid byte code", 165 zap.String("byteCode", cfg.RawByteCode), 166 zap.Error(err), 167 ) 168 } 169 if cfg.AppendContractAddress { 170 addr, err := address.FromString(cfg.ContractAddressToAppend) 171 if err != nil { 172 log.L().Panic( 173 "invalid contract address to append", 174 zap.String("contractAddressToAppend", cfg.ContractAddressToAppend), 175 zap.Error(err), 176 ) 177 } 178 ba := addr.Bytes() 179 ba = append(make([]byte, 12), ba...) 180 byteCode = append(byteCode, ba...) 181 } 182 183 return byteCode 184 } 185 186 func (cfg *ExecutionConfig) Amount() *big.Int { 187 amount, ok := new(big.Int).SetString(cfg.RawAmount, 10) 188 if !ok { 189 log.L().Panic("invalid amount", zap.String("amount", cfg.RawAmount)) 190 } 191 192 return amount 193 } 194 195 func (cfg *ExecutionConfig) GasPrice() *big.Int { 196 price, ok := new(big.Int).SetString(cfg.RawGasPrice, 10) 197 if !ok { 198 log.L().Panic("invalid gas price", zap.String("gasPrice", cfg.RawGasPrice)) 199 } 200 201 return price 202 } 203 204 func (cfg *ExecutionConfig) GasLimit() uint64 { 205 return uint64(cfg.RawGasLimit) 206 } 207 208 func (cfg *ExecutionConfig) AccessList() types.AccessList { 209 if len(cfg.RawAccessList) == 0 { 210 return nil 211 } 212 accessList := make(types.AccessList, len(cfg.RawAccessList)) 213 for i, rawAccessList := range cfg.RawAccessList { 214 accessList[i].Address = common.HexToAddress(rawAccessList.Address) 215 if numKey := len(rawAccessList.StorageKeys); numKey > 0 { 216 accessList[i].StorageKeys = make([]common.Hash, numKey) 217 for j, rawStorageKey := range rawAccessList.StorageKeys { 218 accessList[i].StorageKeys[j] = common.HexToHash(rawStorageKey) 219 } 220 } 221 } 222 return accessList 223 } 224 225 func (cfg *ExecutionConfig) ExpectedGasConsumed() uint64 { 226 return uint64(cfg.RawExpectedGasConsumed) 227 } 228 229 func (cfg *ExecutionConfig) ExpectedReturnValue() []byte { 230 retval, err := hex.DecodeString(cfg.RawReturnValue) 231 if err != nil { 232 log.L().Panic( 233 "invalid return value", 234 zap.String("returnValue", cfg.RawReturnValue), 235 zap.Error(err), 236 ) 237 } 238 239 return retval 240 } 241 242 type SmartContractTest struct { 243 // the order matters 244 InitGenesis GenesisBlockHeight `json:"initGenesis"` 245 InitBalances []ExpectedBalance `json:"initBalances"` 246 Deployments []ExecutionConfig `json:"deployments"` 247 Executions []ExecutionConfig `json:"executions"` 248 } 249 250 func NewSmartContractTest(t *testing.T, file string) { 251 require := require.New(t) 252 jsonFile, err := os.Open(file) 253 require.NoError(err) 254 sctBytes, err := io.ReadAll(jsonFile) 255 require.NoError(err) 256 sct := &SmartContractTest{} 257 require.NoError(json.Unmarshal(sctBytes, sct)) 258 sct.run(require) 259 } 260 261 func readExecution( 262 bc blockchain.Blockchain, 263 sf factory.Factory, 264 dao blockdao.BlockDAO, 265 ap actpool.ActPool, 266 ecfg *ExecutionConfig, 267 contractAddr string, 268 ) ([]byte, *action.Receipt, error) { 269 log.S().Info(ecfg.Comment) 270 state, err := accountutil.AccountState(genesis.WithGenesisContext(context.Background(), bc.Genesis()), sf, ecfg.Executor()) 271 if err != nil { 272 return nil, nil, err 273 } 274 exec, err := action.NewExecutionWithAccessList( 275 contractAddr, 276 state.PendingNonce(), 277 ecfg.Amount(), 278 ecfg.GasLimit(), 279 ecfg.GasPrice(), 280 ecfg.ByteCode(), 281 ecfg.AccessList(), 282 ) 283 if err != nil { 284 return nil, nil, err 285 } 286 addr := ecfg.PrivateKey().PublicKey().Address() 287 if addr == nil { 288 return nil, nil, errors.New("failed to get address") 289 } 290 ctx, err := bc.Context(context.Background()) 291 if err != nil { 292 return nil, nil, err 293 } 294 ctx = evm.WithHelperCtx(ctx, evm.HelperContext{ 295 GetBlockHash: dao.GetBlockHash, 296 GetBlockTime: getBlockTimeForTest, 297 }) 298 return sf.SimulateExecution(ctx, addr, exec) 299 } 300 301 func (sct *SmartContractTest) runExecutions( 302 bc blockchain.Blockchain, 303 sf factory.Factory, 304 dao blockdao.BlockDAO, 305 ap actpool.ActPool, 306 ecfgs []*ExecutionConfig, 307 contractAddrs []string, 308 ) ([]*action.Receipt, *ExpectedBlockInfo, error) { 309 nonces := map[string]uint64{} 310 hashes := []hash.Hash256{} 311 for i, ecfg := range ecfgs { 312 log.S().Info(ecfg.Comment) 313 nonce := uint64(1) 314 var ok bool 315 executor := ecfg.Executor() 316 if nonce, ok = nonces[executor.String()]; !ok { 317 state, err := accountutil.AccountState(genesis.WithGenesisContext(context.Background(), bc.Genesis()), sf, executor) 318 if err != nil { 319 return nil, nil, err 320 } 321 nonce = state.PendingNonce() 322 } 323 nonces[executor.String()] = nonce 324 exec, err := action.NewExecutionWithAccessList( 325 contractAddrs[i], 326 nonce, 327 ecfg.Amount(), 328 ecfg.GasLimit(), 329 ecfg.GasPrice(), 330 ecfg.ByteCode(), 331 ecfg.AccessList(), 332 ) 333 if err != nil { 334 return nil, nil, err 335 } 336 builder := &action.EnvelopeBuilder{} 337 builder.SetAction(exec). 338 SetNonce(exec.Nonce()). 339 SetGasLimit(ecfg.GasLimit()). 340 SetGasPrice(ecfg.GasPrice()) 341 if sct.InitGenesis.IsShanghai { 342 builder.SetChainID(bc.ChainID()) 343 } 344 elp := builder.Build() 345 selp, err := action.Sign(elp, ecfg.PrivateKey()) 346 if err != nil { 347 return nil, nil, err 348 } 349 if err := ap.Add(context.Background(), selp); err != nil { 350 return nil, nil, err 351 } 352 selpHash, err := selp.Hash() 353 if err != nil { 354 return nil, nil, err 355 } 356 hashes = append(hashes, selpHash) 357 } 358 blk, err := bc.MintNewBlock(fixedTime) 359 if err != nil { 360 return nil, nil, err 361 } 362 363 if err := bc.CommitBlock(blk); err != nil { 364 return nil, nil, err 365 } 366 receipts, err := dao.GetReceipts(blk.Height()) 367 if err != nil { 368 return nil, nil, err 369 } 370 receiptMap := make(map[hash.Hash256]*action.Receipt, len(receipts)) 371 for _, receipt := range receipts { 372 receiptMap[receipt.ActionHash] = receipt 373 } 374 receipts = receipts[:0] 375 for _, h := range hashes { 376 receipt, ok := receiptMap[h] 377 if !ok { 378 return nil, nil, errors.Errorf("failed to find receipt for action %x", h) 379 } 380 receipts = append(receipts, receipt) 381 } 382 stateRootHash, txRootHash, receiptRootHash := blk.DeltaStateDigest(), blk.TxRoot(), blk.ReceiptRoot() 383 blkInfo := &ExpectedBlockInfo{ 384 hex.EncodeToString(txRootHash[:]), 385 hex.EncodeToString(stateRootHash[:]), 386 hex.EncodeToString(receiptRootHash[:]), 387 } 388 return receipts, blkInfo, nil 389 } 390 391 func (sct *SmartContractTest) prepareBlockchain( 392 ctx context.Context, 393 cfg config.Config, 394 r *require.Assertions, 395 ) (blockchain.Blockchain, factory.Factory, blockdao.BlockDAO, actpool.ActPool) { 396 defer func() { 397 delete(cfg.Plugins, config.GatewayPlugin) 398 }() 399 cfg.Plugins[config.GatewayPlugin] = true 400 cfg.Chain.EnableAsyncIndexWrite = false 401 cfg.Genesis.EnableGravityChainVoting = false 402 testTriePath, err := testutil.PathOfTempFile("trie") 403 r.NoError(err) 404 defer testutil.CleanupPath(testTriePath) 405 406 cfg.Chain.TrieDBPath = testTriePath 407 cfg.ActPool.MinGasPriceStr = "0" 408 if sct.InitGenesis.IsBering { 409 cfg.Genesis.Blockchain.AleutianBlockHeight = 0 410 cfg.Genesis.Blockchain.BeringBlockHeight = 0 411 } 412 cfg.Genesis.HawaiiBlockHeight = 0 413 if sct.InitGenesis.IsIceland { 414 cfg.Genesis.CookBlockHeight = 0 415 cfg.Genesis.DardanellesBlockHeight = 0 416 cfg.Genesis.DaytonaBlockHeight = 0 417 cfg.Genesis.EasterBlockHeight = 0 418 cfg.Genesis.FbkMigrationBlockHeight = 0 419 cfg.Genesis.FairbankBlockHeight = 0 420 cfg.Genesis.GreenlandBlockHeight = 0 421 cfg.Genesis.IcelandBlockHeight = 0 422 } 423 if sct.InitGenesis.IsLondon { 424 // London is enabled at okhotsk height 425 cfg.Genesis.Blockchain.JutlandBlockHeight = 0 426 cfg.Genesis.Blockchain.KamchatkaBlockHeight = 0 427 cfg.Genesis.Blockchain.LordHoweBlockHeight = 0 428 cfg.Genesis.Blockchain.MidwayBlockHeight = 0 429 cfg.Genesis.Blockchain.NewfoundlandBlockHeight = 0 430 cfg.Genesis.Blockchain.OkhotskBlockHeight = 0 431 } 432 if sct.InitGenesis.IsShanghai { 433 // Shanghai is enabled at Sumatra height 434 cfg.Genesis.Blockchain.PalauBlockHeight = 0 435 cfg.Genesis.Blockchain.QuebecBlockHeight = 0 436 cfg.Genesis.Blockchain.RedseaBlockHeight = 0 437 cfg.Genesis.Blockchain.SumatraBlockHeight = 0 438 cfg.Genesis.ActionGasLimit = 10000000 439 } 440 for _, expectedBalance := range sct.InitBalances { 441 cfg.Genesis.InitBalanceMap[expectedBalance.Account] = expectedBalance.Balance().String() 442 } 443 registry := protocol.NewRegistry() 444 acc := account.NewProtocol(rewarding.DepositGas) 445 r.NoError(acc.Register(registry)) 446 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 447 r.NoError(rp.Register(registry)) 448 // create state factory 449 var sf factory.Factory 450 var daoKV db.KVStore 451 452 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 453 if cfg.Chain.EnableTrielessStateDB { 454 if cfg.Chain.EnableStateDBCaching { 455 daoKV, err = db.CreateKVStoreWithCache(cfg.DB, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize) 456 } else { 457 daoKV, err = db.CreateKVStore(cfg.DB, cfg.Chain.TrieDBPath) 458 } 459 r.NoError(err) 460 sf, err = factory.NewStateDB(factoryCfg, daoKV, factory.RegistryStateDBOption(registry)) 461 } else { 462 sf, err = factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 463 } 464 r.NoError(err) 465 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 466 r.NoError(err) 467 // create indexer 468 indexer, err := blockindex.NewIndexer(db.NewMemKVStore(), cfg.Genesis.Hash()) 469 r.NoError(err) 470 // create BlockDAO 471 store, err := filedao.NewFileDAOInMemForTest() 472 r.NoError(err) 473 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize) 474 r.NotNil(dao) 475 bc := blockchain.NewBlockchain( 476 cfg.Chain, 477 cfg.Genesis, 478 dao, 479 factory.NewMinter(sf, ap), 480 blockchain.BlockValidatorOption(block.NewValidator( 481 sf, 482 protocol.NewGenericValidator(sf, accountutil.AccountState), 483 )), 484 ) 485 reward := rewarding.NewProtocol(cfg.Genesis.Rewarding) 486 r.NoError(reward.Register(registry)) 487 488 r.NotNil(bc) 489 execution := NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, getBlockTimeForTest) 490 r.NoError(execution.Register(registry)) 491 r.NoError(bc.Start(ctx)) 492 493 return bc, sf, dao, ap 494 } 495 496 func (sct *SmartContractTest) deployContracts( 497 bc blockchain.Blockchain, 498 sf factory.Factory, 499 dao blockdao.BlockDAO, 500 ap actpool.ActPool, 501 r *require.Assertions, 502 ) (contractAddresses []string) { 503 for i, contract := range sct.Deployments { 504 if contract.AppendContractAddress { 505 contract.ContractAddressToAppend = contractAddresses[contract.ContractIndexToAppend] 506 } 507 receipts, _, err := sct.runExecutions(bc, sf, dao, ap, []*ExecutionConfig{&contract}, []string{action.EmptyAddress}) 508 r.NoError(err) 509 r.Equal(1, len(receipts)) 510 receipt := receipts[0] 511 r.NotNil(receipt) 512 if sct.InitGenesis.IsBering { 513 // if it is post bering, it compares the status with expected status 514 r.Equal(sct.Deployments[i].ExpectedStatus, receipt.Status) 515 if receipt.Status != uint64(iotextypes.ReceiptStatus_Success) { 516 return []string{} 517 } 518 } else { 519 if !sct.Deployments[i].Failed { 520 r.Equal(uint64(iotextypes.ReceiptStatus_Success), receipt.Status, i) 521 } else { 522 r.Equal(uint64(iotextypes.ReceiptStatus_Failure), receipt.Status, i) 523 return []string{} 524 } 525 } 526 if sct.Deployments[i].ExpectedGasConsumed() != 0 { 527 r.Equal(sct.Deployments[i].ExpectedGasConsumed(), receipt.GasConsumed) 528 } 529 530 addr, _ := address.FromString(receipt.ContractAddress) 531 c, err := readCode(sf, addr.Bytes()) 532 r.NoError(err) 533 if contract.AppendContractAddress { 534 lenOfByteCode := len(contract.ByteCode()) 535 r.True(bytes.Contains(contract.ByteCode()[:lenOfByteCode-32], c)) 536 } else { 537 r.True(bytes.Contains(sct.Deployments[i].ByteCode(), c)) 538 } 539 contractAddresses = append(contractAddresses, receipt.ContractAddress) 540 } 541 return 542 } 543 544 func (sct *SmartContractTest) run(r *require.Assertions) { 545 // prepare blockchain 546 ctx := context.Background() 547 cfg := deepcopy.Copy(config.Default).(config.Config) 548 cfg.Chain.ProducerPrivKey = identityset.PrivateKey(28).HexString() 549 cfg.Chain.EnableTrielessStateDB = false 550 bc, sf, dao, ap := sct.prepareBlockchain(ctx, cfg, r) 551 defer func() { 552 r.NoError(bc.Stop(ctx)) 553 }() 554 ctx = genesis.WithGenesisContext(context.Background(), bc.Genesis()) 555 // deploy smart contract 556 contractAddresses := sct.deployContracts(bc, sf, dao, ap, r) 557 if len(contractAddresses) == 0 { 558 return 559 } 560 561 // run executions 562 for i, exec := range sct.Executions { 563 contractAddr := contractAddresses[exec.ContractIndex] 564 if exec.AppendContractAddress { 565 exec.ContractAddressToAppend = contractAddresses[exec.ContractIndexToAppend] 566 } 567 var retval []byte 568 var receipt *action.Receipt 569 var blkInfo *ExpectedBlockInfo 570 var err error 571 if exec.ReadOnly { 572 retval, receipt, err = readExecution(bc, sf, dao, ap, &exec, contractAddr) 573 r.NoError(err) 574 expected := exec.ExpectedReturnValue() 575 if len(expected) == 0 { 576 r.Equal(0, len(retval)) 577 } else { 578 r.Equal(expected, retval) 579 } 580 } else { 581 var receipts []*action.Receipt 582 receipts, blkInfo, err = sct.runExecutions(bc, sf, dao, ap, []*ExecutionConfig{&exec}, []string{contractAddr}) 583 r.NoError(err) 584 r.Equal(1, len(receipts)) 585 receipt = receipts[0] 586 r.NotNil(receipt) 587 } 588 589 if sct.InitGenesis.IsBering { 590 // if it is post bering, it compares the status with expected status 591 r.Equal(exec.ExpectedStatus, receipt.Status) 592 } else { 593 if exec.Failed { 594 r.Equal(uint64(iotextypes.ReceiptStatus_Failure), receipt.Status) 595 } else { 596 r.Equal(uint64(iotextypes.ReceiptStatus_Success), receipt.Status) 597 } 598 } 599 if exec.ExpectedGasConsumed() != 0 { 600 r.Equal(exec.ExpectedGasConsumed(), receipt.GasConsumed, i) 601 } 602 if exec.ExpectedBlockInfos != (ExpectedBlockInfo{}) { 603 r.Equal(exec.ExpectedBlockInfos.ReceiptRootHash, blkInfo.ReceiptRootHash) 604 r.Equal(exec.ExpectedBlockInfos.TxRootHash, blkInfo.TxRootHash) 605 r.Equal(exec.ExpectedBlockInfos.StateRootHash, blkInfo.StateRootHash) 606 } 607 for _, expectedBalance := range exec.ExpectedBalances { 608 account := expectedBalance.Account 609 if account == "" { 610 account = contractAddr 611 } 612 addr, err := address.FromString(account) 613 r.NoError(err) 614 state, err := accountutil.AccountState(ctx, sf, addr) 615 r.NoError(err) 616 r.Equal( 617 0, 618 state.Balance.Cmp(expectedBalance.Balance()), 619 "balance of account %s is different from expectation, %d vs %d", 620 account, 621 state.Balance, 622 expectedBalance.Balance(), 623 ) 624 } 625 if receipt.Status == uint64(iotextypes.ReceiptStatus_Success) { 626 r.Equal(len(exec.ExpectedLogs), len(receipt.Logs()), i) 627 // TODO: check value of logs 628 } 629 if receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) { 630 r.Equal(exec.ExpectedErrorMsg, receipt.ExecutionRevertMsg()) 631 } 632 } 633 } 634 635 func TestProtocol_Validate(t *testing.T) { 636 require := require.New(t) 637 p := NewProtocol(func(uint64) (hash.Hash256, error) { 638 return hash.ZeroHash256, nil 639 }, rewarding.DepositGasWithSGD, nil, getBlockTimeForTest) 640 641 cases := []struct { 642 name string 643 height uint64 644 size uint64 645 expectErr error 646 }{ 647 {"limit 32KB", 0, 32683, nil}, 648 {"exceed 32KB", 0, 32684, action.ErrOversizedData}, 649 {"limit 48KB", genesis.Default.SumatraBlockHeight, uint64(_executionSizeLimit48KB), nil}, 650 {"exceed 48KB", genesis.Default.SumatraBlockHeight, uint64(_executionSizeLimit48KB) + 1, action.ErrOversizedData}, 651 } 652 653 for i := range cases { 654 t.Run(cases[i].name, func(t *testing.T) { 655 ex, err := action.NewExecution("2", uint64(1), big.NewInt(0), uint64(0), big.NewInt(0), make([]byte, cases[i].size)) 656 require.NoError(err) 657 ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) 658 ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ 659 BlockHeight: cases[i].height, 660 }) 661 ctx = protocol.WithFeatureCtx(ctx) 662 require.Equal(cases[i].expectErr, errors.Cause(p.Validate(ctx, ex, nil))) 663 }) 664 } 665 } 666 667 func TestProtocol_Handle(t *testing.T) { 668 testEVM := func(t *testing.T) { 669 log.S().Info("Test EVM") 670 require := require.New(t) 671 672 cfg := config.Default 673 defer func() { 674 delete(cfg.Plugins, config.GatewayPlugin) 675 }() 676 677 testTriePath, err := testutil.PathOfTempFile("trie") 678 require.NoError(err) 679 testDBPath, err := testutil.PathOfTempFile("db") 680 require.NoError(err) 681 testIndexPath, err := testutil.PathOfTempFile("index") 682 require.NoError(err) 683 defer func() { 684 testutil.CleanupPath(testTriePath) 685 testutil.CleanupPath(testDBPath) 686 testutil.CleanupPath(testIndexPath) 687 }() 688 689 cfg.Plugins[config.GatewayPlugin] = true 690 cfg.Chain.TrieDBPath = testTriePath 691 cfg.Chain.ChainDBPath = testDBPath 692 cfg.Chain.IndexDBPath = testIndexPath 693 cfg.Chain.EnableAsyncIndexWrite = false 694 cfg.Genesis.EnableGravityChainVoting = false 695 cfg.ActPool.MinGasPriceStr = "0" 696 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(1000000000).String() 697 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 698 699 registry := protocol.NewRegistry() 700 acc := account.NewProtocol(rewarding.DepositGas) 701 require.NoError(acc.Register(registry)) 702 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 703 require.NoError(rp.Register(registry)) 704 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 705 db2, err := db.CreateKVStoreWithCache(cfg.DB, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize) 706 require.NoError(err) 707 // create state factory 708 sf, err := factory.NewStateDB(factoryCfg, db2, factory.RegistryStateDBOption(registry)) 709 require.NoError(err) 710 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 711 require.NoError(err) 712 // create indexer 713 cfg.DB.DbPath = cfg.Chain.IndexDBPath 714 indexer, err := blockindex.NewIndexer(db.NewBoltDB(cfg.DB), hash.ZeroHash256) 715 require.NoError(err) 716 // create BlockDAO 717 cfg.DB.DbPath = cfg.Chain.ChainDBPath 718 store, err := filedao.NewFileDAOInMemForTest() 719 require.NoError(err) 720 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize) 721 require.NotNil(dao) 722 bc := blockchain.NewBlockchain( 723 cfg.Chain, 724 cfg.Genesis, 725 dao, 726 factory.NewMinter(sf, ap), 727 blockchain.BlockValidatorOption(block.NewValidator( 728 sf, 729 protocol.NewGenericValidator(sf, accountutil.AccountState), 730 )), 731 ) 732 exeProtocol := NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, getBlockTimeForTest) 733 require.NoError(exeProtocol.Register(registry)) 734 require.NoError(bc.Start(ctx)) 735 require.NotNil(bc) 736 defer func() { 737 require.NoError(bc.Stop(ctx)) 738 }() 739 740 data, _ := hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029") 741 execution, err := action.NewExecution(action.EmptyAddress, 1, big.NewInt(0), uint64(100000), big.NewInt(0), data) 742 require.NoError(err) 743 744 bd := &action.EnvelopeBuilder{} 745 elp := bd.SetAction(execution). 746 SetNonce(1). 747 SetGasLimit(100000).Build() 748 selp, err := action.Sign(elp, identityset.PrivateKey(27)) 749 require.NoError(err) 750 751 require.NoError(ap.Add(context.Background(), selp)) 752 blk, err := bc.MintNewBlock(fixedTime) 753 require.NoError(err) 754 require.NoError(bc.CommitBlock(blk)) 755 require.Equal(1, len(blk.Receipts)) 756 757 eHash, err := selp.Hash() 758 require.NoError(err) 759 r := blk.Receipts[0] 760 require.Equal(eHash, r.ActionHash) 761 contract, err := address.FromString(r.ContractAddress) 762 require.NoError(err) 763 764 // test IsContract 765 state, err := accountutil.AccountState(ctx, sf, contract) 766 require.NoError(err) 767 require.True(state.IsContract()) 768 769 c, err := readCode(sf, contract.Bytes()) 770 require.NoError(err) 771 require.Equal(data[31:], c) 772 773 exe, _, err := blk.ActionByHash(eHash) 774 require.NoError(err) 775 exeHash, err := exe.Hash() 776 require.NoError(err) 777 require.Equal(eHash, exeHash) 778 779 addr27 := hash.BytesToHash160(identityset.Address(27).Bytes()) 780 total, err := indexer.GetActionCountByAddress(addr27) 781 require.NoError(err) 782 exes, err := indexer.GetActionsByAddress(addr27, 0, total) 783 require.NoError(err) 784 require.Equal(1, len(exes)) 785 require.Equal(eHash[:], exes[0]) 786 787 actIndex, err := indexer.GetActionIndex(eHash[:]) 788 require.NoError(err) 789 blkHash, err := dao.GetBlockHash(actIndex.BlockHeight()) 790 require.NoError(err) 791 require.Equal(blk.HashBlock(), blkHash) 792 793 // store to key 0 794 data, _ = hex.DecodeString("60fe47b1000000000000000000000000000000000000000000000000000000000000000f") 795 execution, err = action.NewExecution(r.ContractAddress, 2, big.NewInt(0), uint64(120000), big.NewInt(0), data) 796 require.NoError(err) 797 798 bd = &action.EnvelopeBuilder{} 799 elp = bd.SetAction(execution). 800 SetNonce(2). 801 SetGasLimit(120000).Build() 802 selp, err = action.Sign(elp, identityset.PrivateKey(27)) 803 require.NoError(err) 804 805 log.S().Infof("execution %+v", execution) 806 807 require.NoError(ap.Add(context.Background(), selp)) 808 blk, err = bc.MintNewBlock(fixedTime) 809 require.NoError(err) 810 require.NoError(bc.CommitBlock(blk)) 811 require.Equal(1, len(blk.Receipts)) 812 813 // TODO (zhi): reenable the unit test 814 /* 815 ws, err = sf.NewWorkingSet() 816 require.NoError(err) 817 stateDB = evm.NewStateDBAdapter(ws, uint64(0), true, hash.ZeroHash256) 818 var emptyEVMHash common.Hash 819 v := stateDB.GetState(evmContractAddrHash, emptyEVMHash) 820 require.Equal(byte(15), v[31]) 821 */ 822 eHash, err = selp.Hash() 823 require.NoError(err) 824 require.Equal(eHash, blk.Receipts[0].ActionHash) 825 826 // read from key 0 827 data, err = hex.DecodeString("6d4ce63c") 828 require.NoError(err) 829 execution, err = action.NewExecution(r.ContractAddress, 3, big.NewInt(0), uint64(120000), big.NewInt(0), data) 830 require.NoError(err) 831 832 bd = &action.EnvelopeBuilder{} 833 elp = bd.SetAction(execution). 834 SetNonce(3). 835 SetGasLimit(120000).Build() 836 selp, err = action.Sign(elp, identityset.PrivateKey(27)) 837 require.NoError(err) 838 839 log.S().Infof("execution %+v", execution) 840 require.NoError(ap.Add(context.Background(), selp)) 841 blk, err = bc.MintNewBlock(fixedTime) 842 require.NoError(err) 843 require.NoError(bc.CommitBlock(blk)) 844 require.Equal(1, len(blk.Receipts)) 845 846 eHash, err = selp.Hash() 847 require.NoError(err) 848 require.Equal(eHash, blk.Receipts[0].ActionHash) 849 850 data, _ = hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029") 851 execution1, err := action.NewExecution(action.EmptyAddress, 4, big.NewInt(0), uint64(100000), big.NewInt(10), data) 852 require.NoError(err) 853 bd = &action.EnvelopeBuilder{} 854 855 elp = bd.SetAction(execution1). 856 SetNonce(4). 857 SetGasLimit(100000).SetGasPrice(big.NewInt(10)).Build() 858 selp, err = action.Sign(elp, identityset.PrivateKey(27)) 859 require.NoError(err) 860 861 require.NoError(ap.Add(context.Background(), selp)) 862 blk, err = bc.MintNewBlock(fixedTime) 863 require.NoError(err) 864 require.NoError(bc.CommitBlock(blk)) 865 require.Equal(1, len(blk.Receipts)) 866 } 867 868 t.Run("EVM", func(t *testing.T) { 869 testEVM(t) 870 }) 871 /** 872 * source of smart contract: https://etherscan.io/address/0x6fb3e0a217407efff7ca062d46c26e5d60a14d69#code 873 */ 874 t.Run("ERC20", func(t *testing.T) { 875 NewSmartContractTest(t, "testdata/erc20.json") 876 }) 877 /** 878 * Source of smart contract: https://etherscan.io/address/0x8dd5fbce2f6a956c3022ba3663759011dd51e73e#code 879 */ 880 t.Run("DelegateERC20", func(t *testing.T) { 881 NewSmartContractTest(t, "testdata/delegate_erc20.json") 882 }) 883 /* 884 * Source code: https://kovan.etherscan.io/address/0x81f85886749cbbf3c2ec742db7255c6b07c63c69 885 */ 886 t.Run("InfiniteLoop", func(t *testing.T) { 887 NewSmartContractTest(t, "testdata/infiniteloop.json") 888 }) 889 // RollDice 890 t.Run("RollDice", func(t *testing.T) { 891 NewSmartContractTest(t, "testdata/rolldice.json") 892 }) 893 // ChangeState 894 t.Run("ChangeState", func(t *testing.T) { 895 NewSmartContractTest(t, "testdata/changestate.json") 896 }) 897 // array-return 898 t.Run("ArrayReturn", func(t *testing.T) { 899 NewSmartContractTest(t, "testdata/array-return.json") 900 }) 901 // basic-token 902 t.Run("BasicToken", func(t *testing.T) { 903 NewSmartContractTest(t, "testdata/basic-token.json") 904 }) 905 // call-dynamic 906 t.Run("CallDynamic", func(t *testing.T) { 907 NewSmartContractTest(t, "testdata/call-dynamic.json") 908 }) 909 // factory 910 t.Run("Factory", func(t *testing.T) { 911 NewSmartContractTest(t, "testdata/factory.json") 912 }) 913 // mapping-delete 914 t.Run("MappingDelete", func(t *testing.T) { 915 NewSmartContractTest(t, "testdata/mapping-delete.json") 916 }) 917 // f.value 918 t.Run("F.value", func(t *testing.T) { 919 NewSmartContractTest(t, "testdata/f.value.json") 920 }) 921 // proposal 922 t.Run("Proposal", func(t *testing.T) { 923 NewSmartContractTest(t, "testdata/proposal.json") 924 }) 925 // public-length 926 t.Run("PublicLength", func(t *testing.T) { 927 NewSmartContractTest(t, "testdata/public-length.json") 928 }) 929 // public-mapping 930 t.Run("PublicMapping", func(t *testing.T) { 931 NewSmartContractTest(t, "testdata/public-mapping.json") 932 }) 933 // no-variable-length-returns 934 t.Run("NoVariableLengthReturns", func(t *testing.T) { 935 NewSmartContractTest(t, "testdata/no-variable-length-returns.json") 936 }) 937 // tuple 938 t.Run("Tuple", func(t *testing.T) { 939 NewSmartContractTest(t, "testdata/tuple.json") 940 }) 941 // tail-recursion 942 t.Run("TailRecursion", func(t *testing.T) { 943 NewSmartContractTest(t, "testdata/tail-recursion.json") 944 }) 945 // sha3 946 t.Run("Sha3", func(t *testing.T) { 947 NewSmartContractTest(t, "testdata/sha3.json") 948 }) 949 // remove-from-array 950 t.Run("RemoveFromArray", func(t *testing.T) { 951 NewSmartContractTest(t, "testdata/remove-from-array.json") 952 }) 953 // send-eth 954 t.Run("SendEth", func(t *testing.T) { 955 NewSmartContractTest(t, "testdata/send-eth.json") 956 }) 957 // modifier 958 t.Run("Modifier", func(t *testing.T) { 959 NewSmartContractTest(t, "testdata/modifiers.json") 960 }) 961 // multisend 962 t.Run("Multisend", func(t *testing.T) { 963 NewSmartContractTest(t, "testdata/multisend.json") 964 }) 965 t.Run("Multisend2", func(t *testing.T) { 966 NewSmartContractTest(t, "testdata/multisend2.json") 967 }) 968 // reentry 969 t.Run("reentry-attack", func(t *testing.T) { 970 NewSmartContractTest(t, "testdata/reentry-attack.json") 971 }) 972 // cashier 973 t.Run("cashier", func(t *testing.T) { 974 NewSmartContractTest(t, "testdata/cashier.json") 975 }) 976 // wireconnection 977 // [Issue #1422] This unit test proves that there is no problem when we want to deploy and execute the contract 978 // which inherits abstract contract and implements abstract functions and call each other (Utterance() calls utterance()) 979 t.Run("wireconnection", func(t *testing.T) { 980 NewSmartContractTest(t, "testdata/wireconnection.json") 981 }) 982 // gas-test 983 t.Run("gas-test", func(t *testing.T) { 984 NewSmartContractTest(t, "testdata/gas-test.json") 985 }) 986 // storage-test 987 t.Run("storage-test", func(t *testing.T) { 988 NewSmartContractTest(t, "testdata/storage-test.json") 989 }) 990 // cashier-bering 991 t.Run("cashier-bering", func(t *testing.T) { 992 NewSmartContractTest(t, "testdata/cashier-bering.json") 993 }) 994 // infiniteloop-bering 995 t.Run("infiniteloop-bering", func(t *testing.T) { 996 NewSmartContractTest(t, "testdata/infiniteloop-bering.json") 997 }) 998 // self-destruct 999 t.Run("self-destruct", func(t *testing.T) { 1000 NewSmartContractTest(t, "testdata/self-destruct.json") 1001 }) 1002 // datacopy 1003 t.Run("datacopy", func(t *testing.T) { 1004 NewSmartContractTest(t, "testdata/datacopy.json") 1005 }) 1006 // this test replay CVE-2021-39137 attack, see attack details 1007 // at https://github.com/ethereum/go-ethereum/blob/master/docs/postmortems/2021-08-22-split-postmortem.md 1008 t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) { 1009 NewSmartContractTest(t, "testdata/CVE-2021-39137-attack-replay.json") 1010 }) 1011 } 1012 1013 func TestMaxTime(t *testing.T) { 1014 t.Run("max-time", func(t *testing.T) { 1015 NewSmartContractTest(t, "testdata/maxtime.json") 1016 }) 1017 1018 t.Run("max-time-2", func(t *testing.T) { 1019 NewSmartContractTest(t, "testdata/maxtime2.json") 1020 }) 1021 } 1022 1023 func TestIstanbulEVM(t *testing.T) { 1024 t.Run("ArrayReturn", func(t *testing.T) { 1025 NewSmartContractTest(t, "testdata-istanbul/array-return.json") 1026 }) 1027 t.Run("BasicToken", func(t *testing.T) { 1028 NewSmartContractTest(t, "testdata-istanbul/basic-token.json") 1029 }) 1030 t.Run("CallDynamic", func(t *testing.T) { 1031 NewSmartContractTest(t, "testdata-istanbul/call-dynamic.json") 1032 }) 1033 t.Run("chainid-selfbalance", func(t *testing.T) { 1034 NewSmartContractTest(t, "testdata-istanbul/chainid-selfbalance.json") 1035 }) 1036 t.Run("ChangeState", func(t *testing.T) { 1037 NewSmartContractTest(t, "testdata-istanbul/changestate.json") 1038 }) 1039 t.Run("F.value", func(t *testing.T) { 1040 NewSmartContractTest(t, "testdata-istanbul/f.value.json") 1041 }) 1042 t.Run("Gas-test", func(t *testing.T) { 1043 NewSmartContractTest(t, "testdata-istanbul/gas-test.json") 1044 }) 1045 t.Run("InfiniteLoop", func(t *testing.T) { 1046 NewSmartContractTest(t, "testdata-istanbul/infiniteloop.json") 1047 }) 1048 t.Run("MappingDelete", func(t *testing.T) { 1049 NewSmartContractTest(t, "testdata-istanbul/mapping-delete.json") 1050 }) 1051 t.Run("max-time", func(t *testing.T) { 1052 NewSmartContractTest(t, "testdata-istanbul/maxtime.json") 1053 }) 1054 t.Run("Modifier", func(t *testing.T) { 1055 NewSmartContractTest(t, "testdata-istanbul/modifiers.json") 1056 }) 1057 t.Run("Multisend", func(t *testing.T) { 1058 NewSmartContractTest(t, "testdata-istanbul/multisend.json") 1059 }) 1060 t.Run("NoVariableLengthReturns", func(t *testing.T) { 1061 NewSmartContractTest(t, "testdata-istanbul/no-variable-length-returns.json") 1062 }) 1063 t.Run("PublicMapping", func(t *testing.T) { 1064 NewSmartContractTest(t, "testdata-istanbul/public-mapping.json") 1065 }) 1066 t.Run("reentry-attack", func(t *testing.T) { 1067 NewSmartContractTest(t, "testdata-istanbul/reentry-attack.json") 1068 }) 1069 t.Run("RemoveFromArray", func(t *testing.T) { 1070 NewSmartContractTest(t, "testdata-istanbul/remove-from-array.json") 1071 }) 1072 t.Run("SendEth", func(t *testing.T) { 1073 NewSmartContractTest(t, "testdata-istanbul/send-eth.json") 1074 }) 1075 t.Run("Sha3", func(t *testing.T) { 1076 NewSmartContractTest(t, "testdata-istanbul/sha3.json") 1077 }) 1078 t.Run("storage-test", func(t *testing.T) { 1079 NewSmartContractTest(t, "testdata-istanbul/storage-test.json") 1080 }) 1081 t.Run("TailRecursion", func(t *testing.T) { 1082 NewSmartContractTest(t, "testdata-istanbul/tail-recursion.json") 1083 }) 1084 t.Run("Tuple", func(t *testing.T) { 1085 NewSmartContractTest(t, "testdata-istanbul/tuple.json") 1086 }) 1087 t.Run("wireconnection", func(t *testing.T) { 1088 NewSmartContractTest(t, "testdata-istanbul/wireconnection.json") 1089 }) 1090 t.Run("self-destruct", func(t *testing.T) { 1091 NewSmartContractTest(t, "testdata-istanbul/self-destruct.json") 1092 }) 1093 t.Run("datacopy", func(t *testing.T) { 1094 NewSmartContractTest(t, "testdata-istanbul/datacopy.json") 1095 }) 1096 t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) { 1097 NewSmartContractTest(t, "testdata-istanbul/CVE-2021-39137-attack-replay.json") 1098 }) 1099 t.Run("err-write-protection", func(t *testing.T) { 1100 NewSmartContractTest(t, "testdata-istanbul/write-protection.json") 1101 }) 1102 t.Run("err-write-protection-twice-delta-0", func(t *testing.T) { 1103 // hit errWriteProtection 2 times, delta is 0 1104 NewSmartContractTest(t, "testdata-istanbul/write-protection-001.json") 1105 }) 1106 t.Run("err-write-protection-once-delta-0", func(t *testing.T) { 1107 // hit errWriteProtection 1 times, delta is 0 1108 NewSmartContractTest(t, "testdata-istanbul/write-protection-002.json") 1109 }) 1110 t.Run("err-write-protection-twice-delta-0-0", func(t *testing.T) { 1111 // hit errWriteProtection twice, delta is not 0 1112 NewSmartContractTest(t, "testdata-istanbul/write-protection-003.json") 1113 }) 1114 t.Run("err-write-protection-twice-delta-0-1", func(t *testing.T) { 1115 // hit errWriteProtection twice, first delta is not 0, second delta is 0 1116 NewSmartContractTest(t, "testdata-istanbul/write-protection-004.json") 1117 }) 1118 t.Run("err-write-protection-once-delta-1", func(t *testing.T) { 1119 // hit errWriteProtection once, delta is not 0,but no revert 1120 NewSmartContractTest(t, "testdata-istanbul/write-protection-005.json") 1121 }) 1122 t.Run("err-write-protection-twice-delta-1-1", func(t *testing.T) { 1123 // hit errWriteProtection twice,, first delta is not 0, second delta is not 0, no revert 1124 NewSmartContractTest(t, "testdata-istanbul/write-protection-006.json") 1125 }) 1126 t.Run("err-write-protection-twice-delta-0-1", func(t *testing.T) { 1127 // hit errWriteProtection twice,, first delta is 0, second delta is not 0, no revert 1128 NewSmartContractTest(t, "testdata-istanbul/write-protection-007.json") 1129 }) 1130 t.Run("err-write-protection-call-staticcall-revrt", func(t *testing.T) { 1131 // call -> staticcall -> revrt 1132 NewSmartContractTest(t, "testdata-istanbul/write-protection-008.json") 1133 }) 1134 t.Run("err-write-protection-staticcall-staticcall-revrt", func(t *testing.T) { 1135 // staticcall -> staticcall -> revrt 1136 NewSmartContractTest(t, "testdata-istanbul/write-protection-009.json") 1137 }) 1138 t.Run("err-write-protection-staticcall-staticcall-revrt-1", func(t *testing.T) { 1139 // staticcall -> staticcall -> revrt twice 1140 NewSmartContractTest(t, "testdata-istanbul/write-protection-010.json") 1141 }) 1142 t.Run("iip15-manager test", func(t *testing.T) { 1143 NewSmartContractTest(t, "testdata-istanbul/iip15-manager.json") 1144 }) 1145 } 1146 1147 func TestLondonEVM(t *testing.T) { 1148 t.Run("factory", func(t *testing.T) { 1149 NewSmartContractTest(t, "testdata-london/factory.json") 1150 }) 1151 t.Run("ArrayReturn", func(t *testing.T) { 1152 NewSmartContractTest(t, "testdata-london/array-return.json") 1153 }) 1154 t.Run("BaseFee", func(t *testing.T) { 1155 NewSmartContractTest(t, "testdata-london/basefee.json") 1156 }) 1157 t.Run("BasicToken", func(t *testing.T) { 1158 NewSmartContractTest(t, "testdata-london/basic-token.json") 1159 }) 1160 t.Run("CallDynamic", func(t *testing.T) { 1161 NewSmartContractTest(t, "testdata-london/call-dynamic.json") 1162 }) 1163 t.Run("chainid-selfbalance", func(t *testing.T) { 1164 NewSmartContractTest(t, "testdata-london/chainid-selfbalance.json") 1165 }) 1166 t.Run("ChangeState", func(t *testing.T) { 1167 NewSmartContractTest(t, "testdata-london/changestate.json") 1168 }) 1169 t.Run("F.value", func(t *testing.T) { 1170 NewSmartContractTest(t, "testdata-london/f.value.json") 1171 }) 1172 t.Run("Gas-test", func(t *testing.T) { 1173 NewSmartContractTest(t, "testdata-london/gas-test.json") 1174 }) 1175 t.Run("InfiniteLoop", func(t *testing.T) { 1176 NewSmartContractTest(t, "testdata-london/infiniteloop.json") 1177 }) 1178 t.Run("MappingDelete", func(t *testing.T) { 1179 NewSmartContractTest(t, "testdata-london/mapping-delete.json") 1180 }) 1181 t.Run("max-time", func(t *testing.T) { 1182 NewSmartContractTest(t, "testdata-london/maxtime.json") 1183 }) 1184 t.Run("Modifier", func(t *testing.T) { 1185 NewSmartContractTest(t, "testdata-london/modifiers.json") 1186 }) 1187 t.Run("Multisend", func(t *testing.T) { 1188 NewSmartContractTest(t, "testdata-london/multisend.json") 1189 }) 1190 t.Run("NoVariableLengthReturns", func(t *testing.T) { 1191 NewSmartContractTest(t, "testdata-london/no-variable-length-returns.json") 1192 }) 1193 t.Run("PublicMapping", func(t *testing.T) { 1194 NewSmartContractTest(t, "testdata-london/public-mapping.json") 1195 }) 1196 t.Run("reentry-attack", func(t *testing.T) { 1197 NewSmartContractTest(t, "testdata-london/reentry-attack.json") 1198 }) 1199 t.Run("RemoveFromArray", func(t *testing.T) { 1200 NewSmartContractTest(t, "testdata-london/remove-from-array.json") 1201 }) 1202 t.Run("SendEth", func(t *testing.T) { 1203 NewSmartContractTest(t, "testdata-london/send-eth.json") 1204 }) 1205 t.Run("Sha3", func(t *testing.T) { 1206 NewSmartContractTest(t, "testdata-london/sha3.json") 1207 }) 1208 t.Run("storage-test", func(t *testing.T) { 1209 NewSmartContractTest(t, "testdata-london/storage-test.json") 1210 }) 1211 t.Run("TailRecursion", func(t *testing.T) { 1212 NewSmartContractTest(t, "testdata-london/tail-recursion.json") 1213 }) 1214 t.Run("Tuple", func(t *testing.T) { 1215 NewSmartContractTest(t, "testdata-london/tuple.json") 1216 }) 1217 t.Run("wireconnection", func(t *testing.T) { 1218 NewSmartContractTest(t, "testdata-london/wireconnection.json") 1219 }) 1220 t.Run("self-destruct", func(t *testing.T) { 1221 NewSmartContractTest(t, "testdata-london/self-destruct.json") 1222 }) 1223 t.Run("datacopy", func(t *testing.T) { 1224 NewSmartContractTest(t, "testdata-london/datacopy.json") 1225 }) 1226 t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) { 1227 NewSmartContractTest(t, "testdata-london/CVE-2021-39137-attack-replay.json") 1228 }) 1229 t.Run("difficulty", func(t *testing.T) { 1230 NewSmartContractTest(t, "testdata-london/difficulty.json") 1231 }) 1232 t.Run("push0-invalid", func(t *testing.T) { 1233 NewSmartContractTest(t, "testdata-london/push0.json") 1234 }) 1235 } 1236 1237 func TestShanghaiEVM(t *testing.T) { 1238 t.Run("array-return", func(t *testing.T) { 1239 NewSmartContractTest(t, "testdata-shanghai/array-return.json") 1240 }) 1241 t.Run("basefee", func(t *testing.T) { 1242 NewSmartContractTest(t, "testdata-shanghai/basefee.json") 1243 }) 1244 t.Run("basic-token", func(t *testing.T) { 1245 NewSmartContractTest(t, "testdata-shanghai/basic-token.json") 1246 }) 1247 t.Run("call-dynamic", func(t *testing.T) { 1248 NewSmartContractTest(t, "testdata-shanghai/call-dynamic.json") 1249 }) 1250 t.Run("chainid-selfbalance", func(t *testing.T) { 1251 NewSmartContractTest(t, "testdata-shanghai/chainid-selfbalance.json") 1252 }) 1253 t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) { 1254 NewSmartContractTest(t, "testdata-shanghai/CVE-2021-39137-attack-replay.json") 1255 }) 1256 t.Run("datacopy", func(t *testing.T) { 1257 NewSmartContractTest(t, "testdata-shanghai/datacopy.json") 1258 }) 1259 t.Run("f.value", func(t *testing.T) { 1260 NewSmartContractTest(t, "testdata-shanghai/f.value.json") 1261 }) 1262 t.Run("factory", func(t *testing.T) { 1263 NewSmartContractTest(t, "testdata-shanghai/factory.json") 1264 }) 1265 t.Run("gas-test", func(t *testing.T) { 1266 NewSmartContractTest(t, "testdata-shanghai/gas-test.json") 1267 }) 1268 t.Run("infiniteloop", func(t *testing.T) { 1269 NewSmartContractTest(t, "testdata-shanghai/infiniteloop.json") 1270 }) 1271 t.Run("mapping-delete", func(t *testing.T) { 1272 NewSmartContractTest(t, "testdata-shanghai/mapping-delete.json") 1273 }) 1274 t.Run("maxtime", func(t *testing.T) { 1275 NewSmartContractTest(t, "testdata-shanghai/maxtime.json") 1276 }) 1277 t.Run("modifiers", func(t *testing.T) { 1278 NewSmartContractTest(t, "testdata-shanghai/modifiers.json") 1279 }) 1280 t.Run("multisend", func(t *testing.T) { 1281 NewSmartContractTest(t, "testdata-shanghai/multisend.json") 1282 }) 1283 t.Run("no-variable-length-returns", func(t *testing.T) { 1284 NewSmartContractTest(t, "testdata-shanghai/no-variable-length-returns.json") 1285 }) 1286 t.Run("public-mapping", func(t *testing.T) { 1287 NewSmartContractTest(t, "testdata-shanghai/public-mapping.json") 1288 }) 1289 t.Run("reentry-attack", func(t *testing.T) { 1290 NewSmartContractTest(t, "testdata-shanghai/reentry-attack.json") 1291 }) 1292 t.Run("remove-from-array", func(t *testing.T) { 1293 NewSmartContractTest(t, "testdata-shanghai/remove-from-array.json") 1294 }) 1295 t.Run("self-destruct", func(t *testing.T) { 1296 NewSmartContractTest(t, "testdata-shanghai/self-destruct.json") 1297 }) 1298 t.Run("send-eth", func(t *testing.T) { 1299 NewSmartContractTest(t, "testdata-shanghai/send-eth.json") 1300 }) 1301 t.Run("sha3", func(t *testing.T) { 1302 NewSmartContractTest(t, "testdata-shanghai/sha3.json") 1303 }) 1304 t.Run("storage-test", func(t *testing.T) { 1305 NewSmartContractTest(t, "testdata-shanghai/storage-test.json") 1306 }) 1307 t.Run("tail-recursion", func(t *testing.T) { 1308 NewSmartContractTest(t, "testdata-shanghai/tail-recursion.json") 1309 }) 1310 t.Run("tuple", func(t *testing.T) { 1311 NewSmartContractTest(t, "testdata-shanghai/tuple.json") 1312 }) 1313 t.Run("wireconnection", func(t *testing.T) { 1314 NewSmartContractTest(t, "testdata-shanghai/wireconnection.json") 1315 }) 1316 t.Run("prevrandao", func(t *testing.T) { 1317 NewSmartContractTest(t, "testdata-shanghai/prevrandao.json") 1318 }) 1319 t.Run("push0-valid", func(t *testing.T) { 1320 NewSmartContractTest(t, "testdata-shanghai/push0.json") 1321 }) 1322 } 1323 1324 func benchmarkHotContractWithFactory(b *testing.B, async bool) { 1325 sct := SmartContractTest{ 1326 InitBalances: []ExpectedBalance{ 1327 { 1328 Account: "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", 1329 RawBalance: "1000000000000000000000000000", 1330 }, 1331 }, 1332 Deployments: []ExecutionConfig{ 1333 { 1334 ContractIndex: 0, 1335 RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", 1336 RawByteCode: "608060405234801561001057600080fd5b506040516040806108018339810180604052810190808051906020019092919080519060200190929190505050816004819055508060058190555050506107a58061005c6000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631249c58b1461007d57806327e235e31461009457806353277879146100eb5780636941b84414610142578063810ad50514610199578063a9059cbb14610223575b600080fd5b34801561008957600080fd5b50610092610270565b005b3480156100a057600080fd5b506100d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610475565b6040518082815260200191505060405180910390f35b3480156100f757600080fd5b5061012c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061048d565b6040518082815260200191505060405180910390f35b34801561014e57600080fd5b50610183600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104a5565b6040518082815260200191505060405180910390f35b3480156101a557600080fd5b506101da600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bd565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561022f57600080fd5b5061026e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610501565b005b436004546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115151561032a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f746f6f20736f6f6e20746f206d696e740000000000000000000000000000000081525060200191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600554600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919060010191905055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b46005546040518082815260200191505060405180910390a3565b60016020528060005260406000206000915090505481565b60026020528060005260406000206000915090505481565b60006020528060005260406000206000915090505481565b60036020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156105b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f696e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200182815250600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b4836040518082815260200191505060405180910390a350505600a165627a7a7230582047e5e1380e66d6b109548617ae59ff7baf70ee2d4a6734559b8fc5cabca0870b0029000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000186a0", 1337 RawAmount: "0", 1338 RawGasLimit: 5000000, 1339 RawGasPrice: "0", 1340 }, 1341 }, 1342 } 1343 r := require.New(b) 1344 ctx := context.Background() 1345 cfg := config.Default 1346 cfg.Genesis.NumSubEpochs = uint64(b.N) 1347 cfg.Chain.EnableTrielessStateDB = false 1348 if async { 1349 cfg.Genesis.GreenlandBlockHeight = 0 1350 } else { 1351 cfg.Genesis.GreenlandBlockHeight = 10000000000 1352 } 1353 bc, sf, dao, ap := sct.prepareBlockchain(ctx, cfg, r) 1354 defer func() { 1355 r.NoError(bc.Stop(ctx)) 1356 }() 1357 contractAddresses := sct.deployContracts(bc, sf, dao, ap, r) 1358 r.Equal(1, len(contractAddresses)) 1359 contractAddr := contractAddresses[0] 1360 b.ResetTimer() 1361 for i := 0; i < b.N; i++ { 1362 receipts, _, err := sct.runExecutions( 1363 bc, sf, dao, ap, []*ExecutionConfig{ 1364 { 1365 RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", 1366 RawByteCode: "1249c58b", 1367 RawAmount: "0", 1368 RawGasLimit: 5000000, 1369 RawGasPrice: "0", 1370 Failed: false, 1371 Comment: "mint token", 1372 }, 1373 }, 1374 []string{contractAddr}, 1375 ) 1376 r.NoError(err) 1377 r.Equal(1, len(receipts)) 1378 r.Equal(uint64(1), receipts[0].Status) 1379 ecfgs := []*ExecutionConfig{} 1380 contractAddrs := []string{} 1381 for j := 0; j < 100; j++ { 1382 ecfgs = append(ecfgs, &ExecutionConfig{ 1383 RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", 1384 RawByteCode: fmt.Sprintf("a9059cbb000000000000000000000000123456789012345678900987%016x0000000000000000000000000000000000000000000000000000000000000039", 100*i+j), 1385 RawAmount: "0", 1386 RawGasLimit: 5000000, 1387 RawGasPrice: "0", 1388 Failed: false, 1389 Comment: "send token", 1390 }) 1391 contractAddrs = append(contractAddrs, contractAddr) 1392 } 1393 receipts, _, err = sct.runExecutions(bc, sf, dao, ap, ecfgs, contractAddrs) 1394 r.NoError(err) 1395 for _, receipt := range receipts { 1396 r.Equal(uint64(1), receipt.Status) 1397 } 1398 } 1399 b.StopTimer() 1400 } 1401 1402 func benchmarkHotContractWithStateDB(b *testing.B, cachedStateDBOption bool) { 1403 sct := SmartContractTest{ 1404 InitBalances: []ExpectedBalance{ 1405 { 1406 Account: "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", 1407 RawBalance: "1000000000000000000000000000", 1408 }, 1409 }, 1410 Deployments: []ExecutionConfig{ 1411 { 1412 ContractIndex: 0, 1413 RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", 1414 RawByteCode: "608060405234801561001057600080fd5b506040516040806108018339810180604052810190808051906020019092919080519060200190929190505050816004819055508060058190555050506107a58061005c6000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631249c58b1461007d57806327e235e31461009457806353277879146100eb5780636941b84414610142578063810ad50514610199578063a9059cbb14610223575b600080fd5b34801561008957600080fd5b50610092610270565b005b3480156100a057600080fd5b506100d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610475565b6040518082815260200191505060405180910390f35b3480156100f757600080fd5b5061012c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061048d565b6040518082815260200191505060405180910390f35b34801561014e57600080fd5b50610183600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104a5565b6040518082815260200191505060405180910390f35b3480156101a557600080fd5b506101da600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bd565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561022f57600080fd5b5061026e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610501565b005b436004546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115151561032a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f746f6f20736f6f6e20746f206d696e740000000000000000000000000000000081525060200191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600554600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919060010191905055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b46005546040518082815260200191505060405180910390a3565b60016020528060005260406000206000915090505481565b60026020528060005260406000206000915090505481565b60006020528060005260406000206000915090505481565b60036020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156105b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f696e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200182815250600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b4836040518082815260200191505060405180910390a350505600a165627a7a7230582047e5e1380e66d6b109548617ae59ff7baf70ee2d4a6734559b8fc5cabca0870b0029000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000186a0", 1415 RawAmount: "0", 1416 RawGasLimit: 5000000, 1417 RawGasPrice: "0", 1418 }, 1419 }, 1420 } 1421 r := require.New(b) 1422 ctx := context.Background() 1423 cfg := config.Default 1424 cfg.Genesis.NumSubEpochs = uint64(b.N) 1425 if cachedStateDBOption { 1426 cfg.Chain.EnableStateDBCaching = true 1427 } else { 1428 cfg.Chain.EnableStateDBCaching = false 1429 } 1430 bc, sf, dao, ap := sct.prepareBlockchain(ctx, cfg, r) 1431 defer func() { 1432 r.NoError(bc.Stop(ctx)) 1433 }() 1434 contractAddresses := sct.deployContracts(bc, sf, dao, ap, r) 1435 r.Equal(1, len(contractAddresses)) 1436 contractAddr := contractAddresses[0] 1437 b.ResetTimer() 1438 for i := 0; i < b.N; i++ { 1439 receipts, _, err := sct.runExecutions( 1440 bc, sf, dao, ap, []*ExecutionConfig{ 1441 { 1442 RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", 1443 RawByteCode: "1249c58b", 1444 RawAmount: "0", 1445 RawGasLimit: 5000000, 1446 RawGasPrice: "0", 1447 Failed: false, 1448 Comment: "mint token", 1449 }, 1450 }, 1451 []string{contractAddr}, 1452 ) 1453 r.NoError(err) 1454 r.Equal(1, len(receipts)) 1455 r.Equal(uint64(1), receipts[0].Status) 1456 ecfgs := []*ExecutionConfig{} 1457 contractAddrs := []string{} 1458 for j := 0; j < 100; j++ { 1459 ecfgs = append(ecfgs, &ExecutionConfig{ 1460 RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", 1461 RawByteCode: fmt.Sprintf("a9059cbb000000000000000000000000123456789012345678900987%016x0000000000000000000000000000000000000000000000000000000000000039", 100*i+j), 1462 RawAmount: "0", 1463 RawGasLimit: 5000000, 1464 RawGasPrice: "0", 1465 Failed: false, 1466 Comment: "send token", 1467 }) 1468 contractAddrs = append(contractAddrs, contractAddr) 1469 } 1470 receipts, _, err = sct.runExecutions(bc, sf, dao, ap, ecfgs, contractAddrs) 1471 r.NoError(err) 1472 for _, receipt := range receipts { 1473 r.Equal(uint64(1), receipt.Status) 1474 } 1475 } 1476 b.StopTimer() 1477 } 1478 1479 func BenchmarkHotContract(b *testing.B) { 1480 b.Run("async mode", func(b *testing.B) { 1481 benchmarkHotContractWithFactory(b, true) 1482 }) 1483 b.Run("sync mode", func(b *testing.B) { 1484 benchmarkHotContractWithFactory(b, false) 1485 }) 1486 b.Run("cachedStateDB", func(b *testing.B) { 1487 benchmarkHotContractWithStateDB(b, true) 1488 }) 1489 b.Run("defaultStateDB", func(b *testing.B) { 1490 benchmarkHotContractWithStateDB(b, false) 1491 }) 1492 } 1493 1494 func getBlockTimeForTest(h uint64) (time.Time, error) { 1495 return fixedTime.Add(time.Duration(h) * 5 * time.Second), nil 1496 }