github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/integrity/integrity_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 integrity 7 8 import ( 9 "context" 10 "encoding/hex" 11 "fmt" 12 "math/big" 13 "sync/atomic" 14 "testing" 15 "time" 16 17 "github.com/ethereum/go-ethereum/crypto" 18 "github.com/golang/mock/gomock" 19 iotexcrypto "github.com/iotexproject/go-pkgs/crypto" 20 "github.com/pkg/errors" 21 "github.com/stretchr/testify/require" 22 23 "github.com/iotexproject/go-pkgs/hash" 24 "github.com/iotexproject/iotex-address/address" 25 "github.com/iotexproject/iotex-proto/golang/iotextypes" 26 27 "github.com/iotexproject/iotex-core/action" 28 "github.com/iotexproject/iotex-core/action/protocol" 29 "github.com/iotexproject/iotex-core/action/protocol/account" 30 accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" 31 "github.com/iotexproject/iotex-core/action/protocol/execution" 32 "github.com/iotexproject/iotex-core/action/protocol/execution/evm" 33 "github.com/iotexproject/iotex-core/action/protocol/poll" 34 "github.com/iotexproject/iotex-core/action/protocol/rewarding" 35 "github.com/iotexproject/iotex-core/action/protocol/rolldpos" 36 "github.com/iotexproject/iotex-core/action/protocol/vote/candidatesutil" 37 "github.com/iotexproject/iotex-core/actpool" 38 "github.com/iotexproject/iotex-core/blockchain" 39 "github.com/iotexproject/iotex-core/blockchain/block" 40 "github.com/iotexproject/iotex-core/blockchain/blockdao" 41 "github.com/iotexproject/iotex-core/blockchain/filedao" 42 "github.com/iotexproject/iotex-core/blockchain/genesis" 43 "github.com/iotexproject/iotex-core/blockindex" 44 "github.com/iotexproject/iotex-core/config" 45 "github.com/iotexproject/iotex-core/db" 46 "github.com/iotexproject/iotex-core/db/trie/mptrie" 47 "github.com/iotexproject/iotex-core/pkg/unit" 48 "github.com/iotexproject/iotex-core/state" 49 "github.com/iotexproject/iotex-core/state/factory" 50 "github.com/iotexproject/iotex-core/test/identityset" 51 "github.com/iotexproject/iotex-core/test/mock/mock_blockcreationsubscriber" 52 "github.com/iotexproject/iotex-core/testutil" 53 ) 54 55 var ( 56 _deployHash hash.Hash256 // in block 1 57 _setHash hash.Hash256 // in block 2 58 _shrHash hash.Hash256 // in block 3 59 _shlHash hash.Hash256 // in block 4 60 _sarHash hash.Hash256 // in block 5 61 _extHash hash.Hash256 // in block 6 62 _crt2Hash hash.Hash256 // in block 7 63 _storeHash hash.Hash256 // in block 8 64 _store2Hash hash.Hash256 // in block 9 65 _setTopic, _ = hex.DecodeString("fe00000000000000000000000000000000000000000000000000000000001f40") // in block 2 66 _getTopic, _ = hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000001") // in block 2 67 _shrTopic, _ = hex.DecodeString("00fe00000000000000000000000000000000000000000000000000000000001f") // in block 3 68 _shlTopic, _ = hex.DecodeString("fe00000000000000000000000000000000000000000000000000000000001f00") // in block 4 69 _sarTopic, _ = hex.DecodeString("fffe00000000000000000000000000000000000000000000000000000000001f") // in block 5 70 _extTopic, _ = hex.DecodeString("4a98ce81a2fd5177f0f42b49cb25b01b720f9ce8019f3937f63b789766c938e2") // in block 6 71 _crt2Topic, _ = hex.DecodeString("0000000000000000000000001895e6033cd1081f18e0bd23a4501d9376028523") // in block 7 72 _preGrPreStore *big.Int 73 _preGrPostStore *big.Int 74 _postGrPostStore *big.Int 75 ) 76 77 func fakeGetBlockTime(height uint64) (time.Time, error) { 78 return time.Time{}, nil 79 } 80 81 func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.BlockDAO, sf factory.Factory, ap actpool.ActPool) error { 82 // Add block 1 83 priKey0 := identityset.PrivateKey(27) 84 ex1, err := action.SignedExecution(action.EmptyAddress, priKey0, 1, big.NewInt(0), 500000, big.NewInt(testutil.TestGasPriceInt64), _constantinopleOpCodeContract) 85 if err != nil { 86 return err 87 } 88 _deployHash, err = ex1.Hash() 89 if err != nil { 90 return err 91 } 92 if err := ap.Add(context.Background(), ex1); err != nil { 93 return err 94 } 95 blockTime := time.Unix(1546329600, 0) 96 blk, err := bc.MintNewBlock(blockTime) 97 if err != nil { 98 return err 99 } 100 if err := bc.CommitBlock(blk); err != nil { 101 return err 102 } 103 104 // get deployed contract address 105 var contract string 106 if dao != nil { 107 r, err := receiptByActionHash(dao, 1, _deployHash) 108 if err != nil { 109 return err 110 } 111 contract = r.ContractAddress 112 } 113 114 addOneBlock := func(contract string, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) (hash.Hash256, error) { 115 ex1, err := action.SignedExecution(contract, priKey0, nonce, amount, gasLimit, gasPrice, data) 116 if err != nil { 117 return hash.ZeroHash256, err 118 } 119 blockTime = blockTime.Add(time.Second) 120 if err := ap.Add(context.Background(), ex1); err != nil { 121 return hash.ZeroHash256, err 122 } 123 blk, err = bc.MintNewBlock(blockTime) 124 if err != nil { 125 return hash.ZeroHash256, err 126 } 127 if err := bc.CommitBlock(blk); err != nil { 128 return hash.ZeroHash256, err 129 } 130 ex1Hash, err := ex1.Hash() 131 if err != nil { 132 return hash.ZeroHash256, err 133 } 134 return ex1Hash, nil 135 } 136 137 var ( 138 zero = big.NewInt(0) 139 gasLimit = testutil.TestGasLimit * 5 140 gasPrice = big.NewInt(testutil.TestGasPriceInt64) 141 ) 142 143 // Add block 2 144 // call set() to set storedData = 0xfe...1f40 145 funcSig := hash.Hash256b([]byte("set(uint256)")) 146 data := append(funcSig[:4], _setTopic...) 147 _setHash, err = addOneBlock(contract, 2, zero, gasLimit, gasPrice, data) 148 if err != nil { 149 return err 150 } 151 152 // Add block 3 153 // call shright() to test SHR opcode, storedData => 0x00fe...1f 154 funcSig = hash.Hash256b([]byte("shright()")) 155 _shrHash, err = addOneBlock(contract, 3, zero, gasLimit, gasPrice, funcSig[:4]) 156 if err != nil { 157 return err 158 } 159 160 // Add block 4 161 // call shleft() to test SHL opcode, storedData => 0xfe...1f00 162 funcSig = hash.Hash256b([]byte("shleft()")) 163 _shlHash, err = addOneBlock(contract, 4, zero, gasLimit, gasPrice, funcSig[:4]) 164 if err != nil { 165 return err 166 } 167 168 // Add block 5 169 // call saright() to test SAR opcode, storedData => 0xfffe...1f 170 funcSig = hash.Hash256b([]byte("saright()")) 171 _sarHash, err = addOneBlock(contract, 5, zero, gasLimit, gasPrice, funcSig[:4]) 172 if err != nil { 173 return err 174 } 175 176 // Add block 6 177 // call getCodeHash() to test EXTCODEHASH opcode 178 funcSig = hash.Hash256b([]byte("getCodeHash(address)")) 179 addr, _ := address.FromString(contract) 180 ethaddr := hash.BytesToHash256(addr.Bytes()) 181 data = append(funcSig[:4], ethaddr[:]...) 182 _extHash, err = addOneBlock(contract, 6, zero, gasLimit, gasPrice, data) 183 if err != nil { 184 return err 185 } 186 187 // Add block 7 188 // call create2() to test CREATE2 opcode 189 funcSig = hash.Hash256b([]byte("create2()")) 190 _crt2Hash, err = addOneBlock(contract, 7, zero, gasLimit, gasPrice, funcSig[:4]) 191 if err != nil { 192 return err 193 } 194 195 // Add block 8 196 // test store out of gas 197 var ( 198 caller = &state.Account{} 199 callerAddr = hash.BytesToHash160(identityset.Address(27).Bytes()) 200 ) 201 _, err = sf.State(caller, protocol.LegacyKeyOption(callerAddr)) 202 if err != nil { 203 return err 204 } 205 _preGrPreStore = new(big.Int).Set(caller.Balance) 206 _storeHash, err = addOneBlock(action.EmptyAddress, 8, unit.ConvertIotxToRau(10000), 3000000, big.NewInt(unit.Qev), _codeStoreOutOfGasContract) 207 if err != nil { 208 return err 209 } 210 211 if dao != nil { 212 r, err := receiptByActionHash(dao, 8, _storeHash) 213 if err != nil { 214 return err 215 } 216 if r.Status != uint64(iotextypes.ReceiptStatus_ErrCodeStoreOutOfGas) { 217 return blockchain.ErrBalance 218 } 219 } 220 221 // Add block 9 222 // test store out of gas 223 _, err = sf.State(caller, protocol.LegacyKeyOption(callerAddr)) 224 if err != nil { 225 return err 226 } 227 _preGrPostStore = new(big.Int).Set(caller.Balance) 228 _store2Hash, err = addOneBlock(action.EmptyAddress, 9, unit.ConvertIotxToRau(10000), 3000000, big.NewInt(unit.Qev), _codeStoreOutOfGasContract) 229 if err != nil { 230 return err 231 } 232 233 if dao != nil { 234 r, err := receiptByActionHash(dao, 9, _store2Hash) 235 if err != nil { 236 return err 237 } 238 if r.Status != uint64(iotextypes.ReceiptStatus_ErrCodeStoreOutOfGas) { 239 return blockchain.ErrBalance 240 } 241 } 242 243 _, err = sf.State(caller, protocol.LegacyKeyOption(callerAddr)) 244 if err != nil { 245 return err 246 } 247 _postGrPostStore = new(big.Int).Set(caller.Balance) 248 return nil 249 } 250 251 func addTestingTsfBlocks(cfg config.Config, bc blockchain.Blockchain, dao blockdao.BlockDAO, ap actpool.ActPool) error { 252 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 253 addOneTsf := func(recipientAddr string, senderPriKey iotexcrypto.PrivateKey, nonce uint64, amount *big.Int, payload []byte, gasLimit uint64, gasPrice *big.Int) error { 254 tx, err := action.SignedTransfer(recipientAddr, senderPriKey, nonce, amount, payload, gasLimit, gasPrice) 255 if err != nil { 256 return err 257 } 258 if err := ap.Add(ctx, tx); err != nil { 259 return err 260 } 261 return nil 262 } 263 addOneExec := func(contractAddr string, executorPriKey iotexcrypto.PrivateKey, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) error { 264 tx, err := action.SignedExecution(contractAddr, executorPriKey, nonce, amount, gasLimit, gasPrice, data) 265 if err != nil { 266 return err 267 } 268 if err := ap.Add(ctx, tx); err != nil { 269 return err 270 } 271 return nil 272 } 273 // Add block 1 274 addr0 := identityset.Address(27).String() 275 if err := addOneTsf(addr0, identityset.PrivateKey(0), 1, big.NewInt(90000000), nil, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 276 return err 277 } 278 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 279 if err != nil { 280 return err 281 } 282 if err := bc.CommitBlock(blk); err != nil { 283 return err 284 } 285 ap.Reset() 286 287 priKey0 := identityset.PrivateKey(27) 288 addr1 := identityset.Address(28).String() 289 priKey1 := identityset.PrivateKey(28) 290 addr2 := identityset.Address(29).String() 291 priKey2 := identityset.PrivateKey(29) 292 addr3 := identityset.Address(30).String() 293 priKey3 := identityset.PrivateKey(30) 294 addr4 := identityset.Address(31).String() 295 priKey4 := identityset.PrivateKey(31) 296 addr5 := identityset.Address(32).String() 297 priKey5 := identityset.PrivateKey(32) 298 addr6 := identityset.Address(33).String() 299 // Add block 2 300 // test --> A, B, C, D, E, F 301 if err := addOneTsf(addr1, priKey0, 1, big.NewInt(20), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 302 return err 303 } 304 if err := addOneTsf(addr2, priKey0, 2, big.NewInt(30), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 305 return err 306 } 307 if err := addOneTsf(addr3, priKey0, 3, big.NewInt(50), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 308 return err 309 } 310 if err := addOneTsf(addr4, priKey0, 4, big.NewInt(70), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 311 return err 312 } 313 if err := addOneTsf(addr5, priKey0, 5, big.NewInt(110), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 314 return err 315 } 316 if err := addOneTsf(addr6, priKey0, 6, big.NewInt(50<<20), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 317 return err 318 } 319 // deploy simple smart contract 320 data, _ := hex.DecodeString("608060405234801561001057600080fd5b50610233806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680635bec9e671461005c57806360fe47b114610073578063c2bc2efc146100a0575b600080fd5b34801561006857600080fd5b506100716100f7565b005b34801561007f57600080fd5b5061009e60048036038101908080359060200190929190505050610143565b005b3480156100ac57600080fd5b506100e1600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061017a565b6040518082815260200191505060405180910390f35b5b6001156101155760008081548092919060010191905055506100f8565b7f8bfaa460932ccf8751604dd60efa3eafa220ec358fccb32ef703f91c509bc3ea60405160405180910390a1565b80600081905550807fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a250565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156101b757600080fd5b6000548273ffffffffffffffffffffffffffffffffffffffff167fbde7a70c2261170a87678200113c8e12f82f63d0a1d1cfa45681cbac328e87e360405160405180910390a360005490509190505600a165627a7a723058203198d0390613dab2dff2fa053c1865e802618d628429b01ab05b8458afc347eb0029") 321 ex1, err := action.SignedExecution(action.EmptyAddress, priKey2, 1, big.NewInt(0), 200000, big.NewInt(testutil.TestGasPriceInt64), data) 322 if err != nil { 323 return err 324 } 325 if err := ap.Add(ctx, ex1); err != nil { 326 return err 327 } 328 _deployHash, err = ex1.Hash() 329 if err != nil { 330 return err 331 } 332 blk, err = bc.MintNewBlock(testutil.TimestampNow()) 333 if err != nil { 334 return err 335 } 336 if err := bc.CommitBlock(blk); err != nil { 337 return err 338 } 339 ap.Reset() 340 341 // get deployed contract address 342 var contract string 343 _, gateway := cfg.Plugins[config.GatewayPlugin] 344 if gateway && !cfg.Chain.EnableAsyncIndexWrite { 345 r, err := receiptByActionHash(dao, 2, _deployHash) 346 if err != nil { 347 return err 348 } 349 contract = r.ContractAddress 350 } 351 352 // Add block 3 353 // Charlie --> A, B, D, E, test 354 if err := addOneTsf(addr1, priKey3, 1, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 355 return err 356 } 357 if err := addOneTsf(addr2, priKey3, 2, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 358 return err 359 } 360 if err := addOneTsf(addr4, priKey3, 3, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 361 return err 362 } 363 if err := addOneTsf(addr5, priKey3, 4, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 364 return err 365 } 366 if err := addOneTsf(addr0, priKey3, 5, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 367 return err 368 } 369 // call set() to set storedData = 0x1f40 370 data, _ = hex.DecodeString("60fe47b1") 371 data = append(data, _setTopic...) 372 ex1, err = action.SignedExecution(contract, priKey2, 2, big.NewInt(0), testutil.TestGasLimit*5, big.NewInt(testutil.TestGasPriceInt64), data) 373 if err != nil { 374 return err 375 } 376 _setHash, err = ex1.Hash() 377 if err != nil { 378 return err 379 } 380 if err := ap.Add(context.Background(), ex1); err != nil { 381 return err 382 } 383 blk, err = bc.MintNewBlock(testutil.TimestampNow()) 384 if err != nil { 385 return err 386 } 387 if err := bc.CommitBlock(blk); err != nil { 388 return err 389 } 390 ap.Reset() 391 392 // Add block 4 393 // Delta --> B, E, F, test 394 if err := addOneTsf(addr2, priKey4, 1, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 395 return err 396 } 397 if err := addOneTsf(addr5, priKey4, 2, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 398 return err 399 } 400 if err := addOneTsf(addr6, priKey4, 3, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 401 return err 402 } 403 if err := addOneTsf(addr0, priKey4, 4, big.NewInt(1), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 404 return err 405 } 406 data, _ = hex.DecodeString("c2bc2efc") 407 data = append(data, _getTopic...) 408 ex1, err = action.SignedExecution(contract, priKey2, 3, big.NewInt(0), testutil.TestGasLimit*5, big.NewInt(testutil.TestGasPriceInt64), data) 409 if err != nil { 410 return err 411 } 412 _sarHash, err = ex1.Hash() 413 if err != nil { 414 return err 415 } 416 if err := ap.Add(context.Background(), ex1); err != nil { 417 return err 418 } 419 blk, err = bc.MintNewBlock(testutil.TimestampNow()) 420 if err != nil { 421 return err 422 } 423 if err := bc.CommitBlock(blk); err != nil { 424 return err 425 } 426 427 // Add block 5 428 // Delta --> A, B, C, D, F, test 429 if err := addOneTsf(addr1, priKey5, 1, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 430 return err 431 } 432 if err := addOneTsf(addr2, priKey5, 2, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 433 return err 434 } 435 if err := addOneTsf(addr3, priKey5, 3, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 436 return err 437 } 438 if err := addOneTsf(addr4, priKey5, 4, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 439 return err 440 } 441 if err := addOneTsf(addr6, priKey5, 5, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 442 return err 443 } 444 if err := addOneTsf(addr0, priKey5, 6, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 445 return err 446 } 447 if err := addOneTsf(addr3, priKey3, 6, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 448 return err 449 } 450 if err := addOneTsf(addr1, priKey1, 1, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)); err != nil { 451 return err 452 } 453 // call set() to set storedData = 0x1f40 454 data, _ = hex.DecodeString("60fe47b1") 455 data = append(data, _setTopic...) 456 if err := addOneExec(contract, priKey2, 4, big.NewInt(0), testutil.TestGasLimit*5, big.NewInt(testutil.TestGasPriceInt64), data); err != nil { 457 return err 458 } 459 data, _ = hex.DecodeString("c2bc2efc") 460 data = append(data, _getTopic...) 461 if err := addOneExec(contract, priKey2, 5, big.NewInt(0), testutil.TestGasLimit*5, big.NewInt(testutil.TestGasPriceInt64), data); err != nil { 462 return err 463 } 464 blk, err = bc.MintNewBlock(testutil.TimestampNow()) 465 if err != nil { 466 return err 467 } 468 return bc.CommitBlock(blk) 469 } 470 471 func TestCreateBlockchain(t *testing.T) { 472 require := require.New(t) 473 ctx := context.Background() 474 475 cfg := config.Default 476 // disable account-based testing 477 cfg.Chain.TrieDBPath = "" 478 cfg.Genesis.EnableGravityChainVoting = false 479 cfg.ActPool.MinGasPriceStr = "0" 480 // create chain 481 registry := protocol.NewRegistry() 482 acc := account.NewProtocol(rewarding.DepositGas) 483 require.NoError(acc.Register(registry)) 484 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 485 require.NoError(rp.Register(registry)) 486 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 487 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 488 require.NoError(err) 489 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 490 require.NoError(err) 491 store, err := filedao.NewFileDAOInMemForTest() 492 require.NoError(err) 493 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 494 bc := blockchain.NewBlockchain( 495 cfg.Chain, 496 cfg.Genesis, 497 dao, 498 factory.NewMinter(sf, ap), 499 blockchain.BlockValidatorOption(block.NewValidator( 500 sf, 501 protocol.NewGenericValidator(sf, accountutil.AccountState), 502 )), 503 ) 504 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 505 require.NoError(ep.Register(registry)) 506 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 507 require.NoError(rewardingProtocol.Register(registry)) 508 require.NoError(bc.Start(ctx)) 509 require.NotNil(bc) 510 height := bc.TipHeight() 511 require.Equal(0, int(height)) 512 defer func() { 513 require.NoError(bc.Stop(ctx)) 514 }() 515 516 // add 4 sample blocks 517 require.NoError(addTestingTsfBlocks(cfg, bc, nil, ap)) 518 height = bc.TipHeight() 519 require.Equal(5, int(height)) 520 } 521 522 func TestGetBlockHash(t *testing.T) { 523 require := require.New(t) 524 ctx := context.Background() 525 526 cfg := config.Default 527 // disable account-based testing 528 cfg.Chain.TrieDBPath = "" 529 cfg.Genesis.EnableGravityChainVoting = false 530 cfg.Genesis.HawaiiBlockHeight = 4 531 cfg.Genesis.MidwayBlockHeight = 9 532 cfg.ActPool.MinGasPriceStr = "0" 533 genesis.SetGenesisTimestamp(cfg.Genesis.Timestamp) 534 block.LoadGenesisHash(&genesis.Default) 535 // create chain 536 registry := protocol.NewRegistry() 537 acc := account.NewProtocol(rewarding.DepositGas) 538 require.NoError(acc.Register(registry)) 539 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 540 require.NoError(rp.Register(registry)) 541 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 542 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 543 require.NoError(err) 544 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 545 require.NoError(err) 546 store, err := filedao.NewFileDAOInMemForTest() 547 require.NoError(err) 548 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 549 bc := blockchain.NewBlockchain( 550 cfg.Chain, 551 cfg.Genesis, 552 dao, 553 factory.NewMinter(sf, ap), 554 blockchain.BlockValidatorOption(block.NewValidator( 555 sf, 556 protocol.NewGenericValidator(sf, accountutil.AccountState), 557 )), 558 ) 559 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 560 require.NoError(ep.Register(registry)) 561 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 562 require.NoError(rewardingProtocol.Register(registry)) 563 require.NoError(bc.Start(ctx)) 564 require.NotNil(bc) 565 height := bc.TipHeight() 566 require.Equal(0, int(height)) 567 defer func() { 568 require.NoError(bc.Stop(ctx)) 569 }() 570 571 addTestingGetBlockHash(t, cfg.Genesis, bc, dao, ap) 572 } 573 574 func addTestingGetBlockHash(t *testing.T, g genesis.Genesis, bc blockchain.Blockchain, dao blockdao.BlockDAO, ap actpool.ActPool) { 575 require := require.New(t) 576 priKey0 := identityset.PrivateKey(27) 577 578 // deploy simple smart contract 579 /* 580 pragma solidity <6.0 >=0.4.24; 581 582 contract Test { 583 event GetBlockhash(bytes32 indexed hash); 584 585 function getBlockHash(uint256 blockNumber) public returns (bytes32) { 586 bytes32 h = blockhash(blockNumber); 587 emit GetBlockhash(h); 588 return h; 589 } 590 } 591 */ 592 ctx := genesis.WithGenesisContext(context.Background(), g) 593 data, _ := hex.DecodeString("6080604052348015600f57600080fd5b5060de8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ee82ac5e14602d575b600080fd5b605660048036036020811015604157600080fd5b8101908080359060200190929190505050606c565b6040518082815260200191505060405180910390f35b60008082409050807f2d93f7749862d33969fb261757410b48065a1bc86a56da5c47820bd063e2338260405160405180910390a28091505091905056fea265627a7a723158200a258cd08ea99ee11aa68c78b6d2bf7ea912615a1e64a81b90a2abca2dd59cfa64736f6c634300050c0032") 594 595 ex1, err := action.SignedExecution(action.EmptyAddress, priKey0, 1, big.NewInt(0), 500000, big.NewInt(testutil.TestGasPriceInt64), data) 596 require.NoError(err) 597 require.NoError(ap.Add(ctx, ex1)) 598 _deployHash, err = ex1.Hash() 599 require.NoError(err) 600 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 601 require.NoError(err) 602 require.NoError(bc.CommitBlock(blk)) 603 604 ap.Reset() 605 blockTime := time.Unix(1546329600, 0) 606 // get deployed contract address 607 var contract string 608 if dao != nil { 609 r, err := receiptByActionHash(dao, 1, _deployHash) 610 require.NoError(err) 611 contract = r.ContractAddress 612 } 613 addOneBlock := func(contract string, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) (hash.Hash256, error) { 614 ex1, err := action.SignedExecution(contract, priKey0, nonce, amount, gasLimit, gasPrice, data) 615 if err != nil { 616 return hash.ZeroHash256, err 617 } 618 blockTime = blockTime.Add(time.Second) 619 if err := ap.Add(ctx, ex1); err != nil { 620 return hash.ZeroHash256, err 621 } 622 blk, err = bc.MintNewBlock(blockTime) 623 if err != nil { 624 return hash.ZeroHash256, err 625 } 626 if err := bc.CommitBlock(blk); err != nil { 627 return hash.ZeroHash256, err 628 } 629 ex1Hash, err := ex1.Hash() 630 if err != nil { 631 return hash.ZeroHash256, err 632 } 633 return ex1Hash, nil 634 } 635 636 getBlockHashCallData := func(x int64) []byte { 637 funcSig := hash.Hash256b([]byte("getBlockHash(uint256)")) 638 // convert block number to uint256 (32-bytes) 639 blockNumber := hash.BytesToHash256(big.NewInt(x).Bytes()) 640 return append(funcSig[:4], blockNumber[:]...) 641 } 642 643 var ( 644 zero = big.NewInt(0) 645 nonce = uint64(2) 646 gasLimit = testutil.TestGasLimit * 5 647 gasPrice = big.NewInt(testutil.TestGasPriceInt64) 648 bcHash hash.Hash256 649 ) 650 tests := []struct { 651 commitHeight uint64 652 getHashHeight uint64 653 }{ 654 {2, 0}, 655 {3, 5}, 656 {4, 1}, 657 {5, 3}, 658 {6, 0}, 659 {7, 6}, 660 {8, 9}, 661 {9, 3}, 662 {10, 9}, 663 {11, 1}, 664 {12, 4}, 665 {13, 0}, 666 {14, 100}, 667 {15, 15}, 668 } 669 for _, test := range tests { 670 h, err := addOneBlock(contract, nonce, zero, gasLimit, gasPrice, getBlockHashCallData(int64(test.getHashHeight))) 671 require.NoError(err) 672 r, err := receiptByActionHash(dao, test.commitHeight, h) 673 require.NoError(err) 674 if test.getHashHeight >= test.commitHeight { 675 bcHash = hash.ZeroHash256 676 } else if test.commitHeight < g.HawaiiBlockHeight { 677 // before hawaii it mistakenly return zero hash 678 // see https://github.com/iotexproject/iotex-core/commit/2585b444214f9009b6356fbaf59c992e8728fc01 679 bcHash = hash.ZeroHash256 680 } else { 681 var targetHeight uint64 682 if test.commitHeight < g.MidwayBlockHeight { 683 targetHeight = test.commitHeight - (test.getHashHeight + 1) 684 } else { 685 targetHeight = test.getHashHeight 686 } 687 bcHash, err = dao.GetBlockHash(targetHeight) 688 require.NoError(err) 689 } 690 require.Equal(r.Logs()[0].Topics[0], bcHash) 691 nonce++ 692 } 693 } 694 695 func TestBlockchain_MintNewBlock(t *testing.T) { 696 cfg := config.Default 697 cfg.Genesis.BlockGasLimit = uint64(100000) 698 cfg.Genesis.EnableGravityChainVoting = false 699 cfg.ActPool.MinGasPriceStr = "0" 700 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 701 registry := protocol.NewRegistry() 702 acc := account.NewProtocol(rewarding.DepositGas) 703 require.NoError(t, acc.Register(registry)) 704 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 705 require.NoError(t, rp.Register(registry)) 706 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 707 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 708 require.NoError(t, err) 709 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 710 require.NoError(t, err) 711 store, err := filedao.NewFileDAOInMemForTest() 712 require.NoError(t, err) 713 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 714 bc := blockchain.NewBlockchain( 715 cfg.Chain, 716 cfg.Genesis, 717 dao, 718 factory.NewMinter(sf, ap), 719 blockchain.BlockValidatorOption(block.NewValidator( 720 sf, 721 protocol.NewGenericValidator(sf, accountutil.AccountState), 722 )), 723 ) 724 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 725 require.NoError(t, ep.Register(registry)) 726 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 727 require.NoError(t, rewardingProtocol.Register(registry)) 728 require.NoError(t, bc.Start(ctx)) 729 defer func() { 730 require.NoError(t, bc.Stop(ctx)) 731 }() 732 733 tsf, err := action.NewTransfer( 734 1, 735 big.NewInt(100000000), 736 identityset.Address(27).String(), 737 []byte{}, uint64(100000), 738 big.NewInt(10), 739 ) 740 require.NoError(t, err) 741 742 data, _ := hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029") 743 execution, err := action.NewExecution(action.EmptyAddress, 2, big.NewInt(0), uint64(100000), big.NewInt(0), data) 744 require.NoError(t, err) 745 746 bd := &action.EnvelopeBuilder{} 747 elp1 := bd.SetAction(tsf). 748 SetNonce(1). 749 SetGasLimit(100000). 750 SetGasPrice(big.NewInt(10)).Build() 751 selp1, err := action.Sign(elp1, identityset.PrivateKey(0)) 752 require.NoError(t, err) 753 require.NoError(t, ap.Add(ctx, selp1)) 754 // This execution should not be included in block because block is out of gas 755 elp2 := bd.SetAction(execution). 756 SetNonce(2). 757 SetGasLimit(100000). 758 SetGasPrice(big.NewInt(10)).Build() 759 selp2, err := action.Sign(elp2, identityset.PrivateKey(0)) 760 require.NoError(t, err) 761 require.NoError(t, ap.Add(ctx, selp2)) 762 763 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 764 require.NoError(t, err) 765 require.Equal(t, 2, len(blk.Actions)) 766 require.Equal(t, 2, len(blk.Receipts)) 767 var gasConsumed uint64 768 for _, receipt := range blk.Receipts { 769 gasConsumed += receipt.GasConsumed 770 } 771 require.True(t, gasConsumed <= cfg.Genesis.BlockGasLimit) 772 } 773 774 func TestBlockchain_MintNewBlock_PopAccount(t *testing.T) { 775 cfg := config.Default 776 cfg.Genesis.EnableGravityChainVoting = false 777 cfg.ActPool.MinGasPriceStr = "0" 778 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 779 registry := protocol.NewRegistry() 780 acc := account.NewProtocol(rewarding.DepositGas) 781 require.NoError(t, acc.Register(registry)) 782 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 783 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 784 require.NoError(t, err) 785 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 786 require.NoError(t, err) 787 store, err := filedao.NewFileDAOInMemForTest() 788 require.NoError(t, err) 789 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 790 bc := blockchain.NewBlockchain( 791 cfg.Chain, 792 cfg.Genesis, 793 dao, 794 factory.NewMinter(sf, ap), 795 blockchain.BlockValidatorOption(block.NewValidator( 796 sf, 797 protocol.NewGenericValidator(sf, accountutil.AccountState), 798 )), 799 ) 800 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 801 require.NoError(t, rp.Register(registry)) 802 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 803 require.NoError(t, ep.Register(registry)) 804 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 805 require.NoError(t, rewardingProtocol.Register(registry)) 806 require.NoError(t, bc.Start(ctx)) 807 defer func() { 808 require.NoError(t, bc.Stop(ctx)) 809 }() 810 811 priKey0 := identityset.PrivateKey(27) 812 addr1 := identityset.Address(28).String() 813 priKey3 := identityset.PrivateKey(30) 814 require.NoError(t, addTestingTsfBlocks(cfg, bc, nil, ap)) 815 816 // test third block 817 bytes := []byte{} 818 for i := 0; i < 1000; i++ { 819 bytes = append(bytes, 1) 820 } 821 for i := uint64(0); i < 300; i++ { 822 tsf, err := action.SignedTransfer(addr1, priKey0, i+7, big.NewInt(2), bytes, 823 19000, big.NewInt(testutil.TestGasPriceInt64)) 824 require.NoError(t, err) 825 require.NoError(t, ap.Add(ctx, tsf)) 826 } 827 transfer1, err := action.SignedTransfer(addr1, priKey3, 7, big.NewInt(2), 828 []byte{}, 10000, big.NewInt(testutil.TestGasPriceInt64)) 829 require.NoError(t, err) 830 require.NoError(t, ap.Add(ctx, transfer1)) 831 832 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 833 require.NoError(t, err) 834 require.NotNil(t, blk) 835 require.Equal(t, 183, len(blk.Actions)) 836 whetherInclude := false 837 for _, action := range blk.Actions { 838 transfer1Hash, err := transfer1.Hash() 839 require.NoError(t, err) 840 actionHash, err := action.Hash() 841 require.NoError(t, err) 842 if transfer1Hash == actionHash { 843 whetherInclude = true 844 break 845 } 846 } 847 require.True(t, whetherInclude) 848 } 849 850 type MockSubscriber struct { 851 counter int32 852 } 853 854 func (ms *MockSubscriber) ReceiveBlock(blk *block.Block) error { 855 tsfs, _ := classifyActions(blk.Actions) 856 atomic.AddInt32(&ms.counter, int32(len(tsfs))) 857 return nil 858 } 859 860 func (ms *MockSubscriber) Counter() int { 861 return int(atomic.LoadInt32(&ms.counter)) 862 } 863 864 func createChain(cfg config.Config, inMem bool) (blockchain.Blockchain, factory.Factory, blockdao.BlockDAO, actpool.ActPool, error) { 865 registry := protocol.NewRegistry() 866 // Create a blockchain from scratch 867 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 868 var ( 869 sf factory.Factory 870 dao blockdao.BlockDAO 871 err error 872 ) 873 if inMem { 874 sf, err = factory.NewStateDB(factoryCfg, db.NewMemKVStore(), factory.RegistryStateDBOption(registry)) 875 } else { 876 db2, err := db.CreateKVStore(cfg.DB, cfg.Chain.TrieDBPath) 877 if err != nil { 878 return nil, nil, nil, nil, err 879 } 880 sf, err = factory.NewStateDB(factoryCfg, db2, factory.RegistryStateDBOption(registry)) 881 } 882 if err != nil { 883 return nil, nil, nil, nil, err 884 } 885 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 886 if err != nil { 887 return nil, nil, nil, nil, err 888 } 889 ap.AddActionEnvelopeValidators( 890 protocol.NewGenericValidator(sf, accountutil.AccountState), 891 ) 892 acc := account.NewProtocol(rewarding.DepositGas) 893 if err = acc.Register(registry); err != nil { 894 return nil, nil, nil, nil, err 895 } 896 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 897 if err = rp.Register(registry); err != nil { 898 return nil, nil, nil, nil, err 899 } 900 // create indexer 901 cfg.DB.DbPath = cfg.Chain.IndexDBPath 902 indexer, err := blockindex.NewIndexer(db.NewBoltDB(cfg.DB), cfg.Genesis.Hash()) 903 if err != nil { 904 return nil, nil, nil, nil, err 905 } 906 var store blockdao.BlockDAO 907 // create BlockDAO 908 if inMem { 909 store, err = filedao.NewFileDAOInMemForTest() 910 if err != nil { 911 return nil, nil, nil, nil, err 912 } 913 } else { 914 cfg.DB.DbPath = cfg.Chain.ChainDBPath 915 store, err = filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 916 } 917 if err != nil { 918 return nil, nil, nil, nil, err 919 } 920 dao = blockdao.NewBlockDAOWithIndexersAndCache( 921 store, 922 []blockdao.BlockIndexer{sf, indexer}, 923 cfg.DB.MaxCacheSize, 924 ) 925 if dao == nil { 926 return nil, nil, nil, nil, err 927 } 928 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 929 if err = ep.Register(registry); err != nil { 930 return nil, nil, nil, nil, err 931 } 932 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 933 if err = rewardingProtocol.Register(registry); err != nil { 934 return nil, nil, nil, nil, err 935 } 936 return blockchain.NewBlockchain( 937 cfg.Chain, 938 cfg.Genesis, 939 dao, 940 factory.NewMinter(sf, ap), 941 blockchain.BlockValidatorOption(block.NewValidator( 942 sf, 943 protocol.NewGenericValidator(sf, accountutil.AccountState), 944 )), 945 ), sf, dao, ap, nil 946 } 947 948 func TestConvertCleanAddress(t *testing.T) { 949 require := require.New(t) 950 951 cfg := config.Default 952 testIndexPath, err := testutil.PathOfTempFile("index") 953 require.NoError(err) 954 955 defer func() { 956 testutil.CleanupPath(testIndexPath) 957 // clear the gateway 958 delete(cfg.Plugins, config.GatewayPlugin) 959 }() 960 961 minGas := big.NewInt(unit.Qev) 962 cfg.Chain.IndexDBPath = testIndexPath 963 cfg.Chain.ProducerPrivKey = "a000000000000000000000000000000000000000000000000000000000000000" 964 cfg.Genesis.EnableGravityChainVoting = false 965 cfg.Plugins[config.GatewayPlugin] = true 966 cfg.Chain.EnableAsyncIndexWrite = false 967 cfg.ActPool.MinGasPriceStr = minGas.String() 968 cfg.Genesis.PacificBlockHeight = 2 969 cfg.Genesis.AleutianBlockHeight = 2 970 cfg.Genesis.BeringBlockHeight = 2 971 cfg.Genesis.CookBlockHeight = 2 972 cfg.Genesis.DaytonaBlockHeight = 2 973 cfg.Genesis.DardanellesBlockHeight = 2 974 cfg.Genesis.EasterBlockHeight = 2 975 cfg.Genesis.FbkMigrationBlockHeight = 2 976 cfg.Genesis.FairbankBlockHeight = 2 977 cfg.Genesis.GreenlandBlockHeight = 2 978 cfg.Genesis.HawaiiBlockHeight = 2 979 cfg.Genesis.IcelandBlockHeight = 2 980 cfg.Genesis.JutlandBlockHeight = 2 981 cfg.Genesis.KamchatkaBlockHeight = 2 982 cfg.Genesis.LordHoweBlockHeight = 2 983 cfg.Genesis.MidwayBlockHeight = 2 984 cfg.Genesis.NewfoundlandBlockHeight = 2 985 cfg.Genesis.OkhotskBlockHeight = 2 986 cfg.Genesis.PalauBlockHeight = 2 987 cfg.Genesis.QuebecBlockHeight = 2 988 cfg.Genesis.RedseaBlockHeight = 2 989 cfg.Genesis.SumatraBlockHeight = 2 990 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() 991 992 ctx := context.Background() 993 bc, sf, dao, ap, err := createChain(cfg, true) 994 require.NoError(err) 995 require.NoError(bc.Start(ctx)) 996 defer func() { 997 require.NoError(bc.Stop(ctx)) 998 }() 999 1000 // Add block 1 1001 nonce, err := ap.GetPendingNonce(identityset.Address(27).String()) 1002 require.NoError(err) 1003 require.EqualValues(1, nonce) 1004 nonce, err = ap.GetPendingNonce(identityset.Address(25).String()) 1005 require.NoError(err) 1006 require.EqualValues(1, nonce) 1007 priKey0 := identityset.PrivateKey(27) 1008 ex1, err := action.SignedExecution(action.EmptyAddress, priKey0, 1, new(big.Int), 500000, minGas, _constantinopleOpCodeContract) 1009 require.NoError(err) 1010 h, _ := ex1.Hash() 1011 require.NoError(ap.Add(ctx, ex1)) 1012 tsf1, err := action.SignedTransfer(identityset.Address(25).String(), priKey0, 2, big.NewInt(10000), nil, 500000, minGas) 1013 require.NoError(err) 1014 require.NoError(ap.Add(ctx, tsf1)) 1015 tsf2, err := action.SignedTransfer(identityset.Address(24).String(), priKey0, 3, big.NewInt(10000), nil, 500000, minGas) 1016 require.NoError(err) 1017 require.NoError(ap.Add(ctx, tsf2)) 1018 deterministic, err := address.FromHex("3fab184622dc19b6109349b94811493bf2a45362") 1019 require.NoError(err) 1020 tsf3, err := action.SignedTransfer(deterministic.String(), priKey0, 4, big.NewInt(10000000000000000), nil, 500000, minGas) 1021 require.NoError(err) 1022 require.NoError(ap.Add(ctx, tsf3)) 1023 blockTime := time.Unix(1546329600, 0) 1024 blk, err := bc.MintNewBlock(blockTime) 1025 require.NoError(err) 1026 require.EqualValues(1, blk.Height()) 1027 require.Equal(5, len(blk.Body.Actions)) 1028 require.NoError(bc.CommitBlock(blk)) 1029 1030 // get deployed contract address 1031 var r *action.Receipt 1032 if dao != nil { 1033 r, err = receiptByActionHash(dao, 1, h) 1034 require.NoError(err) 1035 } 1036 1037 // verify 3 recipients remain legacy fresh accounts 1038 for _, v := range []struct { 1039 a address.Address 1040 b string 1041 }{ 1042 {identityset.Address(24), "100000000000000000000010000"}, 1043 {identityset.Address(25), "100000000000000000000010000"}, 1044 {deterministic, "10000000000000000"}, 1045 } { 1046 a, err := accountutil.AccountState(ctx, sf, v.a) 1047 require.NoError(err) 1048 require.True(a.IsLegacyFreshAccount()) 1049 require.EqualValues(1, a.PendingNonce()) 1050 require.Equal(v.b, a.Balance.String()) 1051 // actpool returns nonce considering legacy fresh account 1052 nonce, err = ap.GetPendingNonce(v.a.String()) 1053 require.NoError(err) 1054 require.Zero(nonce) 1055 } 1056 1057 // Add block 2 1058 t1, _ := action.NewTransfer(0, big.NewInt(100), identityset.Address(27).String(), nil, 500000, minGas) 1059 elp := (&action.EnvelopeBuilder{}).SetNonce(t1.Nonce()). 1060 SetChainID(cfg.Chain.ID). 1061 SetGasPrice(t1.GasPrice()). 1062 SetGasLimit(t1.GasLimit()). 1063 SetAction(t1).Build() 1064 tsf1, err = action.Sign(elp, identityset.PrivateKey(25)) 1065 require.NoError(err) 1066 require.NoError(ap.Add(ctx, tsf1)) 1067 t2, _ := action.NewTransfer(1, big.NewInt(200), identityset.Address(27).String(), nil, 500000, minGas) 1068 elp = (&action.EnvelopeBuilder{}).SetNonce(t2.Nonce()). 1069 SetChainID(cfg.Chain.ID). 1070 SetGasPrice(t2.GasPrice()). 1071 SetGasLimit(t2.GasLimit()). 1072 SetAction(t2).Build() 1073 tsf2, err = action.Sign(elp, identityset.PrivateKey(25)) 1074 require.NoError(err) 1075 require.NoError(ap.Add(ctx, tsf2)) 1076 // call set() to set storedData = 0xfe...1f40 1077 funcSig := hash.Hash256b([]byte("set(uint256)")) 1078 data := append(funcSig[:4], _setTopic...) 1079 e1, _ := action.NewExecution(r.ContractAddress, 0, new(big.Int), 500000, minGas, data) 1080 elp = (&action.EnvelopeBuilder{}).SetNonce(e1.Nonce()). 1081 SetChainID(cfg.Chain.ID). 1082 SetGasPrice(e1.GasPrice()). 1083 SetGasLimit(e1.GasLimit()). 1084 SetAction(e1).Build() 1085 ex1, err = action.Sign(elp, identityset.PrivateKey(24)) 1086 require.NoError(err) 1087 require.NoError(ap.Add(ctx, ex1)) 1088 // deterministic deployment transaction 1089 tx, err := action.DecodeEtherTx("0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222") 1090 require.NoError(err) 1091 require.False(tx.Protected()) 1092 require.Nil(tx.To()) 1093 require.Equal("100000000000", tx.GasPrice().String()) 1094 encoding, sig, pubkey, err := action.ExtractTypeSigPubkey(tx) 1095 require.NoError(err) 1096 require.Equal(iotextypes.Encoding_ETHEREUM_UNPROTECTED, encoding) 1097 // convert tx to envelope 1098 elp, err = (&action.EnvelopeBuilder{}).SetChainID(cfg.Chain.ID).BuildExecution(tx) 1099 require.NoError(err) 1100 ex2, err := (&action.Deserializer{}).SetEvmNetworkID(cfg.Chain.EVMNetworkID). 1101 ActionToSealedEnvelope(&iotextypes.Action{ 1102 Core: elp.Proto(), 1103 SenderPubKey: pubkey.Bytes(), 1104 Signature: sig, 1105 Encoding: encoding, 1106 }) 1107 require.NoError(err) 1108 require.True(address.Equal(ex2.SenderAddress(), deterministic)) 1109 require.True(cfg.Genesis.IsDeployerWhitelisted(ex2.SenderAddress())) 1110 require.NoError(ap.Add(ctx, ex2)) 1111 blockTime = blockTime.Add(time.Second) 1112 blk1, err := bc.MintNewBlock(blockTime) 1113 require.NoError(err) 1114 require.EqualValues(2, blk1.Height()) 1115 require.Equal(5, len(blk1.Body.Actions)) 1116 require.NoError(bc.CommitBlock(blk1)) 1117 1118 // 3 legacy fresh accounts are converted to zero-nonce account 1119 for _, v := range []struct { 1120 a address.Address 1121 nonce uint64 1122 b string 1123 }{ 1124 {identityset.Address(24), 1, "99999999962880000000010000"}, 1125 {identityset.Address(25), 2, "99999999980000000000009700"}, 1126 {deterministic, 1, "6786100000000000"}, 1127 } { 1128 a, err := accountutil.AccountState(ctx, sf, v.a) 1129 require.NoError(err) 1130 require.EqualValues(1, a.AccountType()) 1131 require.Equal(v.nonce, a.PendingNonce()) 1132 require.Equal(v.b, a.Balance.String()) 1133 } 1134 1135 // verify contract execution 1136 h, err = ex1.Hash() 1137 require.NoError(err) 1138 r, err = receiptByActionHash(dao, 2, h) 1139 require.NoError(err) 1140 require.EqualValues(iotextypes.ReceiptStatus_Success, r.Status) 1141 require.EqualValues(2, r.BlockHeight) 1142 require.Equal(h, r.ActionHash) 1143 require.EqualValues(37120, r.GasConsumed) 1144 require.Empty(r.ContractAddress) 1145 1146 // verify deterministic deployment transaction 1147 h, err = ex2.Hash() 1148 require.NoError(err) 1149 require.Equal("eddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26", hex.EncodeToString(h[:])) 1150 r, err = receiptByActionHash(dao, 2, h) 1151 require.NoError(err) 1152 require.EqualValues(iotextypes.ReceiptStatus_Success, r.Status) 1153 require.EqualValues(2, r.BlockHeight) 1154 require.Equal(h, r.ActionHash) 1155 require.EqualValues(32139, r.GasConsumed) 1156 require.Equal("io1fevmgjz8kdu40pvgjgx20ralymqtf9tv3mdu7f", r.ContractAddress) 1157 tl, err := dao.TransactionLogs(2) 1158 require.NoError(err) 1159 require.Equal(4, len(tl.Logs)) 1160 1161 // commit 2 blocks to a new chain 1162 testTriePath2, err := testutil.PathOfTempFile("trie") 1163 require.NoError(err) 1164 testDBPath2, err := testutil.PathOfTempFile("db") 1165 require.NoError(err) 1166 testIndexPath2, err := testutil.PathOfTempFile("index") 1167 require.NoError(err) 1168 1169 defer func() { 1170 testutil.CleanupPath(testTriePath2) 1171 testutil.CleanupPath(testDBPath2) 1172 testutil.CleanupPath(testIndexPath2) 1173 // clear the gateway 1174 delete(cfg.Plugins, config.GatewayPlugin) 1175 }() 1176 1177 cfg.Chain.TrieDBPath = testTriePath2 1178 cfg.Chain.ChainDBPath = testDBPath2 1179 cfg.Chain.IndexDBPath = testIndexPath2 1180 bc2, sf2, dao2, _, err := createChain(cfg, false) 1181 require.NoError(err) 1182 require.NoError(bc2.Start(ctx)) 1183 defer func() { 1184 require.NoError(bc2.Stop(ctx)) 1185 }() 1186 require.NoError(bc2.CommitBlock(blk)) 1187 require.NoError(bc2.CommitBlock(blk1)) 1188 1189 // 3 legacy fresh accounts are converted to zero-nonce account 1190 for _, v := range []struct { 1191 a address.Address 1192 nonce uint64 1193 b string 1194 }{ 1195 {identityset.Address(24), 1, "99999999962880000000010000"}, 1196 {identityset.Address(25), 2, "99999999980000000000009700"}, 1197 {deterministic, 1, "6786100000000000"}, 1198 } { 1199 a, err := accountutil.AccountState(ctx, sf2, v.a) 1200 require.NoError(err) 1201 require.EqualValues(1, a.AccountType()) 1202 require.EqualValues(v.nonce, a.PendingNonce()) 1203 require.Equal(v.b, a.Balance.String()) 1204 } 1205 1206 // verify deterministic deployment transaction 1207 r, err = receiptByActionHash(dao2, 2, h) 1208 require.NoError(err) 1209 require.EqualValues(iotextypes.ReceiptStatus_Success, r.Status) 1210 require.EqualValues(2, r.BlockHeight) 1211 require.Equal(h, r.ActionHash) 1212 require.EqualValues(32139, r.GasConsumed) 1213 require.Equal("io1fevmgjz8kdu40pvgjgx20ralymqtf9tv3mdu7f", r.ContractAddress) 1214 tl, err = dao2.TransactionLogs(2) 1215 require.NoError(err) 1216 require.Equal(4, len(tl.Logs)) 1217 } 1218 1219 func TestConstantinople(t *testing.T) { 1220 require := require.New(t) 1221 testValidateBlockchain := func(cfg config.Config, t *testing.T) { 1222 ctx := context.Background() 1223 1224 registry := protocol.NewRegistry() 1225 // Create a blockchain from scratch 1226 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1227 db2, err := db.CreateKVStore(cfg.DB, cfg.Chain.TrieDBPath) 1228 require.NoError(err) 1229 sf, err := factory.NewFactory(factoryCfg, db2, factory.RegistryOption(registry)) 1230 require.NoError(err) 1231 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 1232 require.NoError(err) 1233 acc := account.NewProtocol(rewarding.DepositGas) 1234 require.NoError(acc.Register(registry)) 1235 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 1236 require.NoError(rp.Register(registry)) 1237 // create indexer 1238 cfg.DB.DbPath = cfg.Chain.IndexDBPath 1239 indexer, err := blockindex.NewIndexer(db.NewBoltDB(cfg.DB), cfg.Genesis.Hash()) 1240 require.NoError(err) 1241 // create BlockDAO 1242 cfg.DB.DbPath = cfg.Chain.ChainDBPath 1243 store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 1244 require.NoError(err) 1245 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize) 1246 require.NotNil(dao) 1247 bc := blockchain.NewBlockchain( 1248 cfg.Chain, 1249 cfg.Genesis, 1250 dao, 1251 factory.NewMinter(sf, ap), 1252 blockchain.BlockValidatorOption(block.NewValidator( 1253 sf, 1254 protocol.NewGenericValidator(sf, accountutil.AccountState), 1255 )), 1256 ) 1257 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 1258 require.NoError(ep.Register(registry)) 1259 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 1260 require.NoError(rewardingProtocol.Register(registry)) 1261 require.NoError(bc.Start(ctx)) 1262 defer func() { 1263 require.NoError(bc.Stop(ctx)) 1264 }() 1265 1266 require.NoError(addTestingConstantinopleBlocks(bc, dao, sf, ap)) 1267 1268 // reason to use hard-coded hash value here: 1269 // this test TestConstantinople() is added when we upgrade our EVM to enable Constantinople 1270 // at that time, the test is run with both EVM version (Byzantium vs. Constantinople), and it generates the 1271 // same exact block hash, so these values stood as gatekeeper for backward-compatibility 1272 hashTopic := []struct { 1273 height uint64 1274 h hash.Hash256 1275 blkHash string 1276 topic []byte 1277 }{ 1278 { 1279 1, 1280 _deployHash, 1281 "2861aecf2b3f91822de00c9f42ca44276e386ac693df363770783bfc133346c3", 1282 nil, 1283 }, 1284 { 1285 2, 1286 _setHash, 1287 "cb0f7895c1fa4f179c0c109835b160d9d1852fce526e12c6b443e86257cadb48", 1288 _setTopic, 1289 }, 1290 { 1291 3, 1292 _shrHash, 1293 "c1337e26e157426dd0af058ed37e329d25dd3e34ed606994a6776b59f988f458", 1294 _shrTopic, 1295 }, 1296 { 1297 4, 1298 _shlHash, 1299 "cf5c2050a261fa7eca45f31a184c6cd1dc737c7fc3088a0983f659b08985521c", 1300 _shlTopic, 1301 }, 1302 { 1303 5, 1304 _sarHash, 1305 "5d76bd9e4be3a60c00761fd141da6bd9c07ab73f472f537845b65679095b0570", 1306 _sarTopic, 1307 }, 1308 { 1309 6, 1310 _extHash, 1311 "c5fd9f372b89265f2423737a6d7b680e9759a4a715b22b04ccf875460c310015", 1312 _extTopic, 1313 }, 1314 { 1315 7, 1316 _crt2Hash, 1317 "53632287a97e4e118302f2d9b54b3f97f62d3533286c4d4eb955627b3602d3b0", 1318 _crt2Topic, 1319 }, 1320 } 1321 1322 // test getReceipt 1323 for _, v := range hashTopic { 1324 ai, err := indexer.GetActionIndex(v.h[:]) 1325 require.NoError(err) 1326 require.Equal(v.height, ai.BlockHeight()) 1327 r, err := receiptByActionHash(dao, v.height, v.h) 1328 require.NoError(err) 1329 require.NotNil(r) 1330 require.Equal(uint64(1), r.Status) 1331 require.Equal(v.h, r.ActionHash) 1332 require.Equal(v.height, r.BlockHeight) 1333 if v.height == 1 { 1334 require.Equal("io1va03q4lcr608dr3nltwm64sfcz05czjuycsqgn", r.ContractAddress) 1335 } else { 1336 require.Empty(r.ContractAddress) 1337 } 1338 blk, err := dao.GetBlockByHeight(v.height) 1339 require.NoError(err) 1340 a, _, err := blk.ActionByHash(v.h) 1341 require.NoError(err) 1342 require.NotNil(a) 1343 aHash, err := a.Hash() 1344 require.NoError(err) 1345 require.Equal(v.h, aHash) 1346 1347 blkHash, err := dao.GetBlockHash(v.height) 1348 require.NoError(err) 1349 require.Equal(v.blkHash, hex.EncodeToString(blkHash[:])) 1350 1351 if v.topic != nil { 1352 funcSig := hash.Hash256b([]byte("Set(uint256)")) 1353 blk, err := dao.GetBlockByHeight(v.height) 1354 require.NoError(err) 1355 f := blk.Header.LogsBloomfilter() 1356 require.NotNil(f) 1357 require.True(f.Exist(funcSig[:])) 1358 require.True(f.Exist(v.topic)) 1359 } 1360 } 1361 1362 storeOutGasTests := []struct { 1363 height uint64 1364 actHash hash.Hash256 1365 status iotextypes.ReceiptStatus 1366 preBalance *big.Int 1367 postBalance *big.Int 1368 }{ 1369 { 1370 8, _storeHash, iotextypes.ReceiptStatus_ErrCodeStoreOutOfGas, _preGrPreStore, _preGrPostStore, 1371 }, 1372 { 1373 9, _store2Hash, iotextypes.ReceiptStatus_ErrCodeStoreOutOfGas, _preGrPostStore, _postGrPostStore, 1374 }, 1375 } 1376 caller := identityset.Address(27) 1377 for _, v := range storeOutGasTests { 1378 r, err := receiptByActionHash(dao, v.height, v.actHash) 1379 require.NoError(err) 1380 require.EqualValues(v.status, r.Status) 1381 1382 // verify transaction log 1383 bLog, err := dao.TransactionLogs(v.height) 1384 require.NoError(err) 1385 tLog := bLog.Logs[0] 1386 // first transaction log is gas fee 1387 tx := tLog.Transactions[0] 1388 require.Equal(tx.Sender, caller.String()) 1389 require.Equal(tx.Recipient, address.RewardingPoolAddr) 1390 require.Equal(iotextypes.TransactionLogType_GAS_FEE, tx.Type) 1391 gasFee, ok := new(big.Int).SetString(tx.Amount, 10) 1392 require.True(ok) 1393 postBalance := new(big.Int).Sub(v.preBalance, gasFee) 1394 1395 if !cfg.Genesis.IsGreenland(v.height) { 1396 // pre-Greenland contains a tx with status = ReceiptStatus_ErrCodeStoreOutOfGas 1397 // due to a bug the transfer is not reverted 1398 require.Equal(2, len(tLog.Transactions)) 1399 // 2nd log is in-contract-transfer 1400 tx = tLog.Transactions[1] 1401 require.Equal(tx.Sender, caller.String()) 1402 require.Equal(iotextypes.TransactionLogType_IN_CONTRACT_TRANSFER, tx.Type) 1403 tsfAmount, ok := new(big.Int).SetString(tx.Amount, 10) 1404 require.True(ok) 1405 postBalance.Sub(postBalance, tsfAmount) 1406 // post = pre - gasFee - in_contract_transfer 1407 require.Equal(v.postBalance, postBalance) 1408 } else { 1409 // post-Greenland fixed that bug, the transfer is reverted so it only contains the gas fee 1410 require.Equal(1, len(tLog.Transactions)) 1411 // post = pre - gasFee (transfer is reverted) 1412 require.Equal(v.postBalance, postBalance) 1413 } 1414 } 1415 1416 // test getActions 1417 addr27 := hash.BytesToHash160(caller.Bytes()) 1418 total, err := indexer.GetActionCountByAddress(addr27) 1419 require.NoError(err) 1420 require.EqualValues(len(hashTopic)+len(storeOutGasTests), total) 1421 actions, err := indexer.GetActionsByAddress(addr27, 0, total) 1422 require.NoError(err) 1423 require.EqualValues(total, len(actions)) 1424 for i := range hashTopic { 1425 require.Equal(hashTopic[i].h[:], actions[i]) 1426 } 1427 for i := range storeOutGasTests { 1428 require.Equal(storeOutGasTests[i].actHash[:], actions[i+len(hashTopic)]) 1429 } 1430 } 1431 1432 cfg := config.Default 1433 testTriePath, err := testutil.PathOfTempFile("trie") 1434 require.NoError(err) 1435 testDBPath, err := testutil.PathOfTempFile("db") 1436 require.NoError(err) 1437 testIndexPath, err := testutil.PathOfTempFile("index") 1438 require.NoError(err) 1439 1440 defer func() { 1441 testutil.CleanupPath(testTriePath) 1442 testutil.CleanupPath(testDBPath) 1443 testutil.CleanupPath(testIndexPath) 1444 // clear the gateway 1445 delete(cfg.Plugins, config.GatewayPlugin) 1446 }() 1447 1448 cfg.Chain.TrieDBPath = testTriePath 1449 cfg.Chain.ChainDBPath = testDBPath 1450 cfg.Chain.IndexDBPath = testIndexPath 1451 cfg.Chain.ProducerPrivKey = "a000000000000000000000000000000000000000000000000000000000000000" 1452 cfg.Genesis.EnableGravityChainVoting = false 1453 cfg.Plugins[config.GatewayPlugin] = true 1454 cfg.Chain.EnableAsyncIndexWrite = false 1455 cfg.ActPool.MinGasPriceStr = "0" 1456 cfg.Genesis.AleutianBlockHeight = 2 1457 cfg.Genesis.BeringBlockHeight = 8 1458 cfg.Genesis.GreenlandBlockHeight = 9 1459 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() 1460 1461 t.Run("test Constantinople contract", func(t *testing.T) { 1462 testValidateBlockchain(cfg, t) 1463 }) 1464 } 1465 1466 func TestLoadBlockchainfromDB(t *testing.T) { 1467 require := require.New(t) 1468 testValidateBlockchain := func(cfg config.Config, t *testing.T) { 1469 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 1470 1471 registry := protocol.NewRegistry() 1472 // Create a blockchain from scratch 1473 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1474 db2, err := db.CreateKVStore(cfg.DB, cfg.Chain.TrieDBPath) 1475 require.NoError(err) 1476 sf, err := factory.NewFactory(factoryCfg, db2, factory.RegistryOption(registry)) 1477 require.NoError(err) 1478 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 1479 require.NoError(err) 1480 acc := account.NewProtocol(rewarding.DepositGas) 1481 require.NoError(acc.Register(registry)) 1482 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 1483 require.NoError(rp.Register(registry)) 1484 var indexer blockindex.Indexer 1485 indexers := []blockdao.BlockIndexer{sf} 1486 if _, gateway := cfg.Plugins[config.GatewayPlugin]; gateway && !cfg.Chain.EnableAsyncIndexWrite { 1487 // create indexer 1488 cfg.DB.DbPath = cfg.Chain.IndexDBPath 1489 indexer, err = blockindex.NewIndexer(db.NewBoltDB(cfg.DB), cfg.Genesis.Hash()) 1490 require.NoError(err) 1491 indexers = append(indexers, indexer) 1492 } 1493 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() 1494 // create BlockDAO 1495 cfg.DB.DbPath = cfg.Chain.ChainDBPath 1496 store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 1497 require.NoError(err) 1498 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, indexers, cfg.DB.MaxCacheSize) 1499 require.NotNil(dao) 1500 bc := blockchain.NewBlockchain( 1501 cfg.Chain, 1502 cfg.Genesis, 1503 dao, 1504 factory.NewMinter(sf, ap), 1505 blockchain.BlockValidatorOption(block.NewValidator( 1506 sf, 1507 protocol.NewGenericValidator(sf, accountutil.AccountState), 1508 )), 1509 ) 1510 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 1511 require.NoError(ep.Register(registry)) 1512 require.NoError(bc.Start(ctx)) 1513 1514 ms := &MockSubscriber{counter: 0} 1515 require.NoError(bc.AddSubscriber(ms)) 1516 require.Equal(0, ms.Counter()) 1517 1518 height := bc.TipHeight() 1519 fmt.Printf("Open blockchain pass, height = %d\n", height) 1520 require.NoError(addTestingTsfBlocks(cfg, bc, dao, ap)) 1521 //make sure pubsub is completed 1522 err = testutil.WaitUntil(200*time.Millisecond, 3*time.Second, func() (bool, error) { 1523 return 24 == ms.Counter(), nil 1524 }) 1525 require.NoError(err) 1526 require.NoError(bc.Stop(ctx)) 1527 1528 // Load a blockchain from DB 1529 bc = blockchain.NewBlockchain( 1530 cfg.Chain, 1531 cfg.Genesis, 1532 dao, 1533 factory.NewMinter(sf, ap), 1534 blockchain.BlockValidatorOption(block.NewValidator( 1535 sf, 1536 protocol.NewGenericValidator(sf, accountutil.AccountState), 1537 )), 1538 ) 1539 require.NoError(bc.Start(ctx)) 1540 defer func() { 1541 require.NoError(bc.Stop(ctx)) 1542 }() 1543 1544 // verify block header hash 1545 for i := uint64(1); i <= 5; i++ { 1546 hash, err := dao.GetBlockHash(i) 1547 require.NoError(err) 1548 height, err = dao.GetBlockHeight(hash) 1549 require.NoError(err) 1550 require.Equal(i, height) 1551 header, err := bc.BlockHeaderByHeight(height) 1552 require.NoError(err) 1553 require.Equal(height, header.Height()) 1554 1555 // bloomfilter only exists after aleutian height 1556 require.Equal(height >= cfg.Genesis.AleutianBlockHeight, header.LogsBloomfilter() != nil) 1557 } 1558 1559 empblk, err := dao.GetBlock(hash.ZeroHash256) 1560 require.Nil(empblk) 1561 require.Error(err) 1562 1563 header, err := bc.BlockHeaderByHeight(60000) 1564 require.Nil(header) 1565 require.Error(err) 1566 1567 // add wrong blocks 1568 h := bc.TipHeight() 1569 blkhash := bc.TipHash() 1570 header, err = bc.BlockHeaderByHeight(h) 1571 require.NoError(err) 1572 require.Equal(blkhash, header.HashBlock()) 1573 fmt.Printf("Current tip = %d hash = %x\n", h, blkhash) 1574 1575 // add block with wrong height 1576 selp, err := action.SignedTransfer(identityset.Address(29).String(), identityset.PrivateKey(27), 1, big.NewInt(50), nil, genesis.Default.ActionGasLimit, big.NewInt(0)) 1577 require.NoError(err) 1578 1579 nblk, err := block.NewTestingBuilder(). 1580 SetHeight(h + 2). 1581 SetPrevBlockHash(blkhash). 1582 SetTimeStamp(testutil.TimestampNow()). 1583 AddActions(selp).SignAndBuild(identityset.PrivateKey(29)) 1584 require.NoError(err) 1585 1586 require.Error(bc.ValidateBlock(&nblk)) 1587 fmt.Printf("Cannot validate block %d: %v\n", header.Height(), err) 1588 1589 // add block with zero prev hash 1590 selp2, err := action.SignedTransfer(identityset.Address(29).String(), identityset.PrivateKey(27), 1, big.NewInt(50), nil, genesis.Default.ActionGasLimit, big.NewInt(0)) 1591 require.NoError(err) 1592 1593 nblk, err = block.NewTestingBuilder(). 1594 SetHeight(h + 1). 1595 SetPrevBlockHash(hash.ZeroHash256). 1596 SetTimeStamp(testutil.TimestampNow()). 1597 AddActions(selp2).SignAndBuild(identityset.PrivateKey(29)) 1598 require.NoError(err) 1599 err = bc.ValidateBlock(&nblk) 1600 require.Error(err) 1601 fmt.Printf("Cannot validate block %d: %v\n", header.Height(), err) 1602 1603 // add existing block again will have no effect 1604 blk, err := dao.GetBlockByHeight(3) 1605 require.NotNil(blk) 1606 require.NoError(err) 1607 require.NoError(bc.CommitBlock(blk)) 1608 fmt.Printf("Cannot add block 3 again: %v\n", err) 1609 1610 // invalid address returns error 1611 _, err = address.FromString("") 1612 require.Contains(err.Error(), "address length = 0, expecting 41") 1613 1614 // valid but unused address should return empty account 1615 addr, err := address.FromString("io1066kus4vlyvk0ljql39fzwqw0k22h7j8wmef3n") 1616 require.NoError(err) 1617 act, err := accountutil.AccountState(ctx, sf, addr) 1618 require.NoError(err) 1619 require.Equal(uint64(1), act.PendingNonce()) 1620 require.Equal(big.NewInt(0), act.Balance) 1621 1622 _, gateway := cfg.Plugins[config.GatewayPlugin] 1623 if gateway && !cfg.Chain.EnableAsyncIndexWrite { 1624 // verify deployed contract 1625 ai, err := indexer.GetActionIndex(_deployHash[:]) 1626 require.NoError(err) 1627 r, err := receiptByActionHash(dao, ai.BlockHeight(), _deployHash) 1628 require.NoError(err) 1629 require.NotNil(r) 1630 require.Equal(uint64(1), r.Status) 1631 require.Equal(uint64(2), r.BlockHeight) 1632 1633 // 2 topics in block 3 calling set() 1634 funcSig := hash.Hash256b([]byte("Set(uint256)")) 1635 blk, err := dao.GetBlockByHeight(3) 1636 require.NoError(err) 1637 f := blk.Header.LogsBloomfilter() 1638 require.NotNil(f) 1639 require.True(f.Exist(funcSig[:])) 1640 require.True(f.Exist(_setTopic)) 1641 r, err = receiptByActionHash(dao, 3, _setHash) 1642 require.NoError(err) 1643 require.EqualValues(1, r.Status) 1644 require.EqualValues(3, r.BlockHeight) 1645 require.Empty(r.ContractAddress) 1646 1647 // 3 topics in block 4 calling get() 1648 funcSig = hash.Hash256b([]byte("Get(address,uint256)")) 1649 blk, err = dao.GetBlockByHeight(4) 1650 require.NoError(err) 1651 f = blk.Header.LogsBloomfilter() 1652 require.NotNil(f) 1653 require.True(f.Exist(funcSig[:])) 1654 require.True(f.Exist(_setTopic)) 1655 require.True(f.Exist(_getTopic)) 1656 r, err = receiptByActionHash(dao, 4, _sarHash) 1657 require.NoError(err) 1658 require.EqualValues(1, r.Status) 1659 require.EqualValues(4, r.BlockHeight) 1660 require.Empty(r.ContractAddress) 1661 1662 // txIndex/logIndex corrected in block 5 1663 blk, err = dao.GetBlockByHeight(5) 1664 require.NoError(err) 1665 verifyTxLogIndex(require, dao, blk, 10, 2) 1666 1667 // verify genesis block index 1668 bi, err := indexer.GetBlockIndex(0) 1669 require.NoError(err) 1670 require.Equal(cfg.Genesis.Hash(), hash.BytesToHash256(bi.Hash())) 1671 require.EqualValues(0, bi.NumAction()) 1672 require.Equal(big.NewInt(0), bi.TsfAmount()) 1673 1674 for h := uint64(1); h <= 5; h++ { 1675 // verify getting number of actions 1676 blk, err = dao.GetBlockByHeight(h) 1677 require.NoError(err) 1678 blkIndex, err := indexer.GetBlockIndex(h) 1679 require.NoError(err) 1680 require.EqualValues(blkIndex.NumAction(), len(blk.Actions)) 1681 1682 // verify getting transfer amount 1683 tsfs, _ := classifyActions(blk.Actions) 1684 tsfa := big.NewInt(0) 1685 for _, tsf := range tsfs { 1686 tsfa.Add(tsfa, tsf.Amount()) 1687 } 1688 require.Equal(blkIndex.TsfAmount(), tsfa) 1689 } 1690 } 1691 } 1692 1693 testTriePath, err := testutil.PathOfTempFile("trie") 1694 require.NoError(err) 1695 testDBPath, err := testutil.PathOfTempFile("db") 1696 require.NoError(err) 1697 testIndexPath, err := testutil.PathOfTempFile("index") 1698 require.NoError(err) 1699 1700 defer func() { 1701 testutil.CleanupPath(testTriePath) 1702 testutil.CleanupPath(testDBPath) 1703 testutil.CleanupPath(testIndexPath) 1704 }() 1705 1706 cfg := config.Default 1707 cfg.Chain.TrieDBPath = testTriePath 1708 cfg.Chain.ChainDBPath = testDBPath 1709 cfg.Chain.IndexDBPath = testIndexPath 1710 cfg.Genesis.EnableGravityChainVoting = false 1711 cfg.ActPool.MinGasPriceStr = "0" 1712 genesis.SetGenesisTimestamp(cfg.Genesis.Timestamp) 1713 block.LoadGenesisHash(&genesis.Default) 1714 1715 t.Run("load blockchain from DB w/o explorer", func(t *testing.T) { 1716 testValidateBlockchain(cfg, t) 1717 }) 1718 1719 testTriePath2, err := testutil.PathOfTempFile("trie") 1720 require.NoError(err) 1721 testDBPath2, err := testutil.PathOfTempFile("db") 1722 require.NoError(err) 1723 testIndexPath2, err := testutil.PathOfTempFile("index") 1724 require.NoError(err) 1725 1726 defer func() { 1727 testutil.CleanupPath(testTriePath2) 1728 testutil.CleanupPath(testDBPath2) 1729 testutil.CleanupPath(testIndexPath2) 1730 // clear the gateway 1731 delete(cfg.Plugins, config.GatewayPlugin) 1732 }() 1733 1734 cfg.Plugins[config.GatewayPlugin] = true 1735 cfg.Chain.TrieDBPath = testTriePath2 1736 cfg.Chain.ChainDBPath = testDBPath2 1737 cfg.Chain.IndexDBPath = testIndexPath2 1738 // test using sm2 signature 1739 cfg.Chain.SignatureScheme = []string{blockchain.SigP256sm2} 1740 cfg.Chain.ProducerPrivKey = "308193020100301306072a8648ce3d020106082a811ccf5501822d0479307702010104202d57ec7da578b98dad465997748ed02af0c69092ad809598073e5a2356c20492a00a06082a811ccf5501822da14403420004223356f0c6f40822ade24d47b0cd10e9285402cbc8a5028a8eec9efba44b8dfe1a7e8bc44953e557b32ec17039fb8018a58d48c8ffa54933fac8030c9a169bf6" 1741 cfg.Chain.EnableAsyncIndexWrite = false 1742 cfg.Genesis.AleutianBlockHeight = 3 1743 cfg.Genesis.MidwayBlockHeight = 5 1744 1745 t.Run("load blockchain from DB", func(t *testing.T) { 1746 testValidateBlockchain(cfg, t) 1747 }) 1748 } 1749 1750 // verify the block contains all tx/log indices up to txIndex and logIndex 1751 func verifyTxLogIndex(r *require.Assertions, dao blockdao.BlockDAO, blk *block.Block, txIndex int, logIndex uint32) { 1752 r.Equal(txIndex, len(blk.Actions)) 1753 receipts, err := dao.GetReceipts(blk.Height()) 1754 r.NoError(err) 1755 r.Equal(txIndex, len(receipts)) 1756 1757 logs := make(map[uint32]bool) 1758 for i := uint32(0); i < logIndex; i++ { 1759 logs[i] = true 1760 } 1761 for i, v := range receipts { 1762 r.EqualValues(1, v.Status) 1763 r.EqualValues(i, v.TxIndex) 1764 h, err := blk.Actions[i].Hash() 1765 r.NoError(err) 1766 r.Equal(h, v.ActionHash) 1767 // verify log index 1768 for _, l := range v.Logs() { 1769 r.Equal(h, l.ActionHash) 1770 r.EqualValues(i, l.TxIndex) 1771 r.True(logs[l.Index]) 1772 delete(logs, l.Index) 1773 } 1774 } 1775 r.Zero(len(logs)) 1776 } 1777 1778 func TestBlockchainInitialCandidate(t *testing.T) { 1779 require := require.New(t) 1780 1781 testTriePath, err := testutil.PathOfTempFile("trie") 1782 require.NoError(err) 1783 testDBPath, err := testutil.PathOfTempFile("db") 1784 require.NoError(err) 1785 testIndexPath, err := testutil.PathOfTempFile("index") 1786 require.NoError(err) 1787 1788 cfg := config.Default 1789 cfg.Chain.TrieDBPath = testTriePath 1790 cfg.Chain.ChainDBPath = testDBPath 1791 cfg.Chain.IndexDBPath = testIndexPath 1792 cfg.Consensus.Scheme = config.RollDPoSScheme 1793 registry := protocol.NewRegistry() 1794 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1795 db2, err := db.CreateKVStore(cfg.DB, cfg.Chain.TrieDBPath) 1796 require.NoError(err) 1797 sf, err := factory.NewFactory(factoryCfg, db2, factory.RegistryOption(registry)) 1798 require.NoError(err) 1799 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 1800 require.NoError(err) 1801 accountProtocol := account.NewProtocol(rewarding.DepositGas) 1802 require.NoError(accountProtocol.Register(registry)) 1803 dbcfg := cfg.DB 1804 dbcfg.DbPath = cfg.Chain.ChainDBPath 1805 store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 1806 require.NoError(err) 1807 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) 1808 bc := blockchain.NewBlockchain( 1809 cfg.Chain, 1810 cfg.Genesis, 1811 dao, 1812 factory.NewMinter(sf, ap), 1813 blockchain.BlockValidatorOption(sf), 1814 ) 1815 rolldposProtocol := rolldpos.NewProtocol( 1816 genesis.Default.NumCandidateDelegates, 1817 genesis.Default.NumDelegates, 1818 genesis.Default.NumSubEpochs, 1819 ) 1820 require.NoError(rolldposProtocol.Register(registry)) 1821 rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) 1822 require.NoError(rewardingProtocol.Register(registry)) 1823 pollProtocol := poll.NewLifeLongDelegatesProtocol(cfg.Genesis.Delegates) 1824 require.NoError(pollProtocol.Register(registry)) 1825 1826 require.NoError(bc.Start(context.Background())) 1827 defer func() { 1828 require.NoError(bc.Stop(context.Background())) 1829 testutil.CleanupPath(testTriePath) 1830 testutil.CleanupPath(testDBPath) 1831 testutil.CleanupPath(testIndexPath) 1832 }() 1833 candidate, _, err := candidatesutil.CandidatesFromDB(sf, 1, true, false) 1834 require.NoError(err) 1835 require.Equal(24, len(candidate)) 1836 } 1837 1838 func TestBlockchain_AccountState(t *testing.T) { 1839 require := require.New(t) 1840 1841 cfg := config.Default 1842 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 1843 registry := protocol.NewRegistry() 1844 acc := account.NewProtocol(rewarding.DepositGas) 1845 require.NoError(acc.Register(registry)) 1846 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1847 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 1848 require.NoError(err) 1849 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 1850 require.NoError(err) 1851 store, err := filedao.NewFileDAOInMemForTest() 1852 require.NoError(err) 1853 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 1854 bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) 1855 require.NoError(bc.Start(ctx)) 1856 require.NotNil(bc) 1857 defer func() { 1858 require.NoError(bc.Stop(ctx)) 1859 }() 1860 s, err := accountutil.AccountState(ctx, sf, identityset.Address(0)) 1861 require.NoError(err) 1862 require.Equal(uint64(1), s.PendingNonce()) 1863 require.Equal(unit.ConvertIotxToRau(100000000), s.Balance) 1864 require.Zero(s.Root) 1865 require.Nil(s.CodeHash) 1866 } 1867 1868 func TestNewAccountAction(t *testing.T) { 1869 require := require.New(t) 1870 1871 cfg := config.Default 1872 cfg.Genesis.OkhotskBlockHeight = 1 1873 ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) 1874 registry := protocol.NewRegistry() 1875 acc := account.NewProtocol(rewarding.DepositGas) 1876 require.NoError(acc.Register(registry)) 1877 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1878 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 1879 require.NoError(err) 1880 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 1881 require.NoError(err) 1882 store, err := filedao.NewFileDAOInMemForTest() 1883 require.NoError(err) 1884 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 1885 bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) 1886 require.NoError(bc.Start(ctx)) 1887 require.NotNil(bc) 1888 defer func() { 1889 require.NoError(bc.Stop(ctx)) 1890 }() 1891 1892 // create a new address, transfer 4 IOTX 1893 newSk, err := iotexcrypto.HexStringToPrivateKey("55499c1b09f687488af9e4ee9e2bd53c7c8c3ddc69d4d9345a04b13030cffabe") 1894 require.NoError(err) 1895 newAddr := newSk.PublicKey().Address() 1896 tx, err := action.SignedTransfer(newAddr.String(), identityset.PrivateKey(0), 1, big.NewInt(4*unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice) 1897 require.NoError(err) 1898 require.NoError(ap.Add(ctx, tx)) 1899 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 1900 require.NoError(err) 1901 require.NoError(bc.CommitBlock(blk)) 1902 ap.Reset() 1903 1904 // initiate transfer from new address 1905 tx, err = action.SignedTransfer(identityset.Address(0).String(), newSk, 0, big.NewInt(unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice) 1906 require.NoError(err) 1907 require.NoError(ap.Add(ctx, tx)) 1908 tx1, err := action.SignedTransfer(identityset.Address(1).String(), newSk, 1, big.NewInt(unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice) 1909 require.NoError(err) 1910 require.NoError(ap.Add(ctx, tx1)) 1911 blk1, err := bc.MintNewBlock(testutil.TimestampNow()) 1912 require.NoError(err) 1913 require.NoError(bc.CommitBlock(blk1)) 1914 ap.Reset() 1915 1916 // commit 2 blocks into a new chain 1917 for _, validateNonce := range []bool{false, true} { 1918 if validateNonce { 1919 cfg.Genesis.PalauBlockHeight = 2 1920 } else { 1921 cfg.Genesis.PalauBlockHeight = 20 1922 } 1923 ctx = genesis.WithGenesisContext(context.Background(), cfg.Genesis) 1924 factoryCfg = factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1925 sf1, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 1926 require.NoError(err) 1927 store, err := filedao.NewFileDAOInMemForTest() 1928 require.NoError(err) 1929 dao1 := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf1}, cfg.DB.MaxCacheSize) 1930 bc1 := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao1, factory.NewMinter(sf1, ap)) 1931 require.NoError(bc1.Start(ctx)) 1932 require.NotNil(bc1) 1933 defer func() { 1934 require.NoError(bc1.Stop(ctx)) 1935 }() 1936 require.NoError(bc1.CommitBlock(blk)) 1937 err = bc1.CommitBlock(blk1) 1938 if validateNonce { 1939 require.NoError(err) 1940 } else { 1941 require.Equal(action.ErrNonceTooHigh, errors.Cause(err)) 1942 } 1943 1944 // verify new addr 1945 s, err := accountutil.AccountState(ctx, sf1, newAddr) 1946 require.NoError(err) 1947 if validateNonce { 1948 require.EqualValues(2, s.PendingNonce()) 1949 require.Equal(big.NewInt(2*unit.Iotx), s.Balance) 1950 } else { 1951 require.Zero(s.PendingNonce()) 1952 require.Equal(big.NewInt(4*unit.Iotx), s.Balance) 1953 } 1954 require.Zero(s.Root) 1955 require.Nil(s.CodeHash) 1956 } 1957 } 1958 1959 func TestBlocks(t *testing.T) { 1960 // This test is used for committing block verify benchmark purpose 1961 t.Skip() 1962 require := require.New(t) 1963 cfg := config.Default 1964 1965 testTriePath, err := testutil.PathOfTempFile("trie") 1966 require.NoError(err) 1967 testDBPath, err := testutil.PathOfTempFile("db") 1968 require.NoError(err) 1969 testIndexPath, err := testutil.PathOfTempFile("index") 1970 require.NoError(err) 1971 1972 a := identityset.Address(28).String() 1973 priKeyA := identityset.PrivateKey(28) 1974 c := identityset.Address(29).String() 1975 1976 cfg.Chain.TrieDBPath = testTriePath 1977 cfg.Chain.ChainDBPath = testDBPath 1978 cfg.Chain.IndexDBPath = testIndexPath 1979 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() 1980 cfg.Genesis.InitBalanceMap[a] = "100000" 1981 cfg.Genesis.InitBalanceMap[c] = "100000" 1982 1983 registry := protocol.NewRegistry() 1984 acc := account.NewProtocol(rewarding.DepositGas) 1985 require.NoError(acc.Register(registry)) 1986 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 1987 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 1988 require.NoError(err) 1989 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 1990 require.NoError(err) 1991 dbcfg := cfg.DB 1992 dbcfg.DbPath = cfg.Chain.ChainDBPath 1993 store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 1994 require.NoError(err) 1995 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) 1996 1997 // Create a blockchain from scratch 1998 bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) 1999 require.NoError(bc.Start(context.Background())) 2000 defer func() { 2001 require.NoError(bc.Stop(context.Background())) 2002 testutil.CleanupPath(testTriePath) 2003 testutil.CleanupPath(testDBPath) 2004 testutil.CleanupPath(testIndexPath) 2005 }() 2006 2007 gasLimit := testutil.TestGasLimit 2008 ctx := protocol.WithBlockCtx(context.Background(), 2009 protocol.BlockCtx{ 2010 Producer: identityset.Address(27), 2011 GasLimit: gasLimit, 2012 }) 2013 ctx = genesis.WithGenesisContext(ctx, cfg.Genesis) 2014 2015 for i := 0; i < 10; i++ { 2016 actionMap := make(map[string][]*action.SealedEnvelope) 2017 actionMap[a] = []*action.SealedEnvelope{} 2018 for i := 0; i < 1000; i++ { 2019 tsf, err := action.SignedTransfer(c, priKeyA, 1, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)) 2020 require.NoError(err) 2021 require.NoError(ap.Add(context.Background(), tsf)) 2022 } 2023 blk, _ := bc.MintNewBlock(testutil.TimestampNow()) 2024 require.NoError(bc.CommitBlock(blk)) 2025 } 2026 } 2027 2028 func TestActions(t *testing.T) { 2029 // This test is used for block verify benchmark purpose 2030 t.Skip() 2031 require := require.New(t) 2032 cfg := config.Default 2033 2034 registry := protocol.NewRegistry() 2035 acc := account.NewProtocol(rewarding.DepositGas) 2036 require.NoError(acc.Register(registry)) 2037 2038 ctx := genesis.WithGenesisContext( 2039 protocol.WithRegistry(context.Background(), registry), 2040 cfg.Genesis, 2041 ) 2042 2043 testTriePath, err := testutil.PathOfTempFile("trie") 2044 require.NoError(err) 2045 testDBPath, err := testutil.PathOfTempFile("db") 2046 require.NoError(err) 2047 testIndexPath, err := testutil.PathOfTempFile("index") 2048 require.NoError(err) 2049 2050 a := identityset.Address(28).String() 2051 priKeyA := identityset.PrivateKey(28) 2052 c := identityset.Address(29).String() 2053 2054 cfg.Chain.TrieDBPath = testTriePath 2055 cfg.Chain.ChainDBPath = testDBPath 2056 cfg.Chain.IndexDBPath = testIndexPath 2057 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() 2058 cfg.Genesis.InitBalanceMap[a] = "100000" 2059 cfg.Genesis.InitBalanceMap[c] = "100000" 2060 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 2061 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 2062 require.NoError(err) 2063 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 2064 require.NoError(err) 2065 dbcfg := cfg.DB 2066 dbcfg.DbPath = cfg.Chain.ChainDBPath 2067 store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 2068 require.NoError(err) 2069 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) 2070 // Create a blockchain from scratch 2071 bc := blockchain.NewBlockchain( 2072 cfg.Chain, 2073 cfg.Genesis, 2074 dao, 2075 factory.NewMinter(sf, ap), 2076 blockchain.BlockValidatorOption(block.NewValidator( 2077 sf, 2078 protocol.NewGenericValidator(sf, accountutil.AccountState), 2079 )), 2080 ) 2081 require.NoError(bc.Start(context.Background())) 2082 defer func() { 2083 require.NoError(bc.Stop(context.Background())) 2084 testutil.CleanupPath(testTriePath) 2085 testutil.CleanupPath(testDBPath) 2086 testutil.CleanupPath(testIndexPath) 2087 }() 2088 2089 gasLimit := testutil.TestGasLimit 2090 ctx = protocol.WithBlockCtx(context.Background(), 2091 protocol.BlockCtx{ 2092 Producer: identityset.Address(27), 2093 GasLimit: gasLimit, 2094 }) 2095 ctx = genesis.WithGenesisContext(ctx, cfg.Genesis) 2096 2097 for i := 0; i < 5000; i++ { 2098 tsf, err := action.SignedTransfer(c, priKeyA, 1, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)) 2099 require.NoError(err) 2100 require.NoError(ap.Add(context.Background(), tsf)) 2101 2102 tsf2, err := action.SignedTransfer(a, priKeyA, 1, big.NewInt(2), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)) 2103 require.NoError(err) 2104 require.NoError(ap.Add(context.Background(), tsf2)) 2105 } 2106 blk, _ := bc.MintNewBlock(testutil.TimestampNow()) 2107 ctx = protocol.WithBlockchainCtx( 2108 ctx, 2109 protocol.BlockchainCtx{ 2110 Tip: protocol.TipInfo{ 2111 Height: 0, 2112 Hash: blk.PrevHash(), 2113 }, 2114 }, 2115 ) 2116 require.NoError(bc.ValidateBlock(blk)) 2117 } 2118 2119 func TestBlockchain_AddRemoveSubscriber(t *testing.T) { 2120 req := require.New(t) 2121 cfg := config.Default 2122 cfg.Genesis.BlockGasLimit = uint64(100000) 2123 cfg.Genesis.EnableGravityChainVoting = false 2124 // create chain 2125 registry := protocol.NewRegistry() 2126 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 2127 sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) 2128 req.NoError(err) 2129 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 2130 req.NoError(err) 2131 store, err := filedao.NewFileDAOInMemForTest() 2132 req.NoError(err) 2133 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) 2134 bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) 2135 // mock 2136 ctrl := gomock.NewController(t) 2137 mb := mock_blockcreationsubscriber.NewMockBlockCreationSubscriber(ctrl) 2138 req.Error(bc.RemoveSubscriber(mb)) 2139 req.NoError(bc.AddSubscriber(mb)) 2140 req.EqualError(bc.AddSubscriber(nil), "subscriber could not be nil") 2141 req.NoError(bc.RemoveSubscriber(mb)) 2142 req.EqualError(bc.RemoveSubscriber(nil), "cannot find subscription") 2143 } 2144 2145 func TestHistoryForAccount(t *testing.T) { 2146 testHistoryForAccount(t, false) 2147 testHistoryForAccount(t, true) 2148 } 2149 2150 func testHistoryForAccount(t *testing.T, statetx bool) { 2151 require := require.New(t) 2152 bc, sf, _, _, ap := newChain(t, statetx) 2153 a := identityset.Address(28) 2154 priKeyA := identityset.PrivateKey(28) 2155 b := identityset.Address(29) 2156 ctx := genesis.WithGenesisContext(context.Background(), bc.Genesis()) 2157 2158 // check the original balance a and b before transfer 2159 AccountA, err := accountutil.AccountState(ctx, sf, a) 2160 require.NoError(err) 2161 AccountB, err := accountutil.AccountState(ctx, sf, b) 2162 require.NoError(err) 2163 require.Equal(big.NewInt(100), AccountA.Balance) 2164 require.Equal(big.NewInt(100), AccountB.Balance) 2165 2166 // make a transfer from a to b 2167 actionMap := make(map[string][]*action.SealedEnvelope) 2168 actionMap[a.String()] = []*action.SealedEnvelope{} 2169 tsf, err := action.SignedTransfer(b.String(), priKeyA, 1, big.NewInt(10), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)) 2170 require.NoError(err) 2171 require.NoError(ap.Add(context.Background(), tsf)) 2172 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 2173 require.NoError(err) 2174 require.NoError(bc.ValidateBlock(blk)) 2175 require.NoError(bc.CommitBlock(blk)) 2176 2177 // check balances after transfer 2178 AccountA, err = accountutil.AccountState(ctx, sf, a) 2179 require.NoError(err) 2180 AccountB, err = accountutil.AccountState(ctx, sf, b) 2181 require.NoError(err) 2182 require.Equal(big.NewInt(90), AccountA.Balance) 2183 require.Equal(big.NewInt(110), AccountB.Balance) 2184 2185 // check history account's balance 2186 if statetx { 2187 _, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), a) 2188 require.Equal(factory.ErrNotSupported, errors.Cause(err)) 2189 _, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), b) 2190 require.Equal(factory.ErrNotSupported, errors.Cause(err)) 2191 } else { 2192 AccountA, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), a) 2193 require.NoError(err) 2194 AccountB, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), b) 2195 require.NoError(err) 2196 require.Equal(big.NewInt(100), AccountA.Balance) 2197 require.Equal(big.NewInt(100), AccountB.Balance) 2198 } 2199 } 2200 2201 func TestHistoryForContract(t *testing.T) { 2202 testHistoryForContract(t, false) 2203 testHistoryForContract(t, true) 2204 } 2205 2206 func testHistoryForContract(t *testing.T, statetx bool) { 2207 require := require.New(t) 2208 bc, sf, _, dao, ap := newChain(t, statetx) 2209 ctx := genesis.WithGenesisContext(context.Background(), bc.Genesis()) 2210 genesisAccount := identityset.Address(27).String() 2211 // deploy and get contract address 2212 contract := deployXrc20(bc, dao, ap, t) 2213 2214 contractAddr, err := address.FromString(contract) 2215 require.NoError(err) 2216 account, err := accountutil.AccountState(ctx, sf, contractAddr) 2217 require.NoError(err) 2218 // check the original balance 2219 balance := BalanceOfContract(contract, genesisAccount, sf, t, account.Root) 2220 expect, ok := new(big.Int).SetString("2000000000000000000000000000", 10) 2221 require.True(ok) 2222 require.Equal(expect, balance) 2223 // make a transfer for contract 2224 makeTransfer(contract, bc, ap, t) 2225 account, err = accountutil.AccountState(ctx, sf, contractAddr) 2226 require.NoError(err) 2227 // check the balance after transfer 2228 balance = BalanceOfContract(contract, genesisAccount, sf, t, account.Root) 2229 expect, ok = new(big.Int).SetString("1999999999999999999999999999", 10) 2230 require.True(ok) 2231 require.Equal(expect, balance) 2232 2233 // check the the original balance again 2234 if statetx { 2235 _, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), contractAddr) 2236 require.True(errors.Cause(err) == factory.ErrNotSupported) 2237 } else { 2238 sr := factory.NewHistoryStateReader(sf, bc.TipHeight()-1) 2239 account, err = accountutil.AccountState(ctx, sr, contractAddr) 2240 require.NoError(err) 2241 balance = BalanceOfContract(contract, genesisAccount, sr, t, account.Root) 2242 expect, ok = new(big.Int).SetString("2000000000000000000000000000", 10) 2243 require.True(ok) 2244 require.Equal(expect, balance) 2245 } 2246 } 2247 2248 func deployXrc20(bc blockchain.Blockchain, dao blockdao.BlockDAO, ap actpool.ActPool, t *testing.T) string { 2249 require := require.New(t) 2250 genesisPriKey := identityset.PrivateKey(27) 2251 // deploy a xrc20 contract with balance 2000000000000000000000000000 2252 data, err := hex.DecodeString("60806040526002805460ff1916601217905534801561001d57600080fd5b506040516107cd3803806107cd83398101604090815281516020808401518385015160025460ff16600a0a84026003819055336000908152600485529586205590850180519395909491019261007592850190610092565b508051610089906001906020840190610092565b5050505061012d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d357805160ff1916838001178555610100565b82800160010185558215610100579182015b828111156101005782518255916020019190600101906100e5565b5061010c929150610110565b5090565b61012a91905b8082111561010c5760008155600101610116565b90565b6106918061013c6000396000f3006080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b3578063095ea7b31461013d57806318160ddd1461017557806323b872dd1461019c578063313ce567146101c657806342966c68146101f1578063670d14b21461020957806370a082311461022a57806395d89b411461024b578063a9059cbb14610260578063dd62ed3e14610286575b600080fd5b3480156100bf57600080fd5b506100c86102ad565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101025781810151838201526020016100ea565b50505050905090810190601f16801561012f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014957600080fd5b50610161600160a060020a036004351660243561033b565b604080519115158252519081900360200190f35b34801561018157600080fd5b5061018a610368565b60408051918252519081900360200190f35b3480156101a857600080fd5b50610161600160a060020a036004358116906024351660443561036e565b3480156101d257600080fd5b506101db6103dd565b6040805160ff9092168252519081900360200190f35b3480156101fd57600080fd5b506101616004356103e6565b34801561021557600080fd5b506100c8600160a060020a036004351661045e565b34801561023657600080fd5b5061018a600160a060020a03600435166104c6565b34801561025757600080fd5b506100c86104d8565b34801561026c57600080fd5b50610284600160a060020a0360043516602435610532565b005b34801561029257600080fd5b5061018a600160a060020a0360043581169060243516610541565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103335780601f1061030857610100808354040283529160200191610333565b820191906000526020600020905b81548152906001019060200180831161031657829003601f168201915b505050505081565b336000908152600560209081526040808320600160a060020a039590951683529390529190912055600190565b60035481565b600160a060020a038316600090815260056020908152604080832033845290915281205482111561039e57600080fd5b600160a060020a03841660009081526005602090815260408083203384529091529020805483900390556103d384848461055e565b5060019392505050565b60025460ff1681565b3360009081526004602052604081205482111561040257600080fd5b3360008181526004602090815260409182902080548690039055600380548690039055815185815291517fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59281900390910190a2506001919050565b60066020908152600091825260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845290918301828280156103335780601f1061030857610100808354040283529160200191610333565b60046020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103335780601f1061030857610100808354040283529160200191610333565b61053d33838361055e565b5050565b600560209081526000928352604080842090915290825290205481565b6000600160a060020a038316151561057557600080fd5b600160a060020a03841660009081526004602052604090205482111561059a57600080fd5b600160a060020a038316600090815260046020526040902054828101116105c057600080fd5b50600160a060020a038083166000818152600460209081526040808320805495891680855282852080548981039091559486905281548801909155815187815291519390950194927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600160a060020a0380841660009081526004602052604080822054928716825290205401811461065f57fe5b505050505600a165627a7a723058207c03ad12a18902cfe387e684509d310abd583d862c11e3ee80c116af8b49ec5c00290000000000000000000000000000000000000000000000000000000077359400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004696f7478000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004696f747800000000000000000000000000000000000000000000000000000000") 2253 require.NoError(err) 2254 execution, err := action.NewExecution(action.EmptyAddress, 3, big.NewInt(0), 1000000, big.NewInt(testutil.TestGasPriceInt64), data) 2255 require.NoError(err) 2256 bd := &action.EnvelopeBuilder{} 2257 elp := bd.SetAction(execution). 2258 SetNonce(3). 2259 SetGasLimit(1000000). 2260 SetGasPrice(big.NewInt(testutil.TestGasPriceInt64)).Build() 2261 selp, err := action.Sign(elp, genesisPriKey) 2262 require.NoError(err) 2263 2264 require.NoError(ap.Add(context.Background(), selp)) 2265 2266 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 2267 require.NoError(err) 2268 require.NoError(bc.CommitBlock(blk)) 2269 selpHash, err := selp.Hash() 2270 require.NoError(err) 2271 r, err := receiptByActionHash(dao, blk.Height(), selpHash) 2272 require.NoError(err) 2273 return r.ContractAddress 2274 } 2275 2276 func BalanceOfContract(contract, genesisAccount string, sr protocol.StateReader, t *testing.T, root hash.Hash256) *big.Int { 2277 require := require.New(t) 2278 addr, err := address.FromString(contract) 2279 require.NoError(err) 2280 addrHash := hash.BytesToHash160(addr.Bytes()) 2281 dbForTrie := protocol.NewKVStoreForTrieWithStateReader(evm.ContractKVNameSpace, sr) 2282 options := []mptrie.Option{ 2283 mptrie.KVStoreOption(dbForTrie), 2284 mptrie.KeyLengthOption(len(hash.Hash256{})), 2285 mptrie.HashFuncOption(func(data []byte) []byte { 2286 h := hash.Hash256b(append(addrHash[:], data...)) 2287 return h[:] 2288 }), 2289 } 2290 options = append(options, mptrie.RootHashOption(root[:])) 2291 tr, err := mptrie.New(options...) 2292 require.NoError(err) 2293 require.NoError(tr.Start(context.Background())) 2294 defer tr.Stop(context.Background()) 2295 // get producer's xrc20 balance 2296 addr, err = address.FromString(genesisAccount) 2297 require.NoError(err) 2298 addrHash = hash.BytesToHash160(addr.Bytes()) 2299 checkData := "000000000000000000000000" + hex.EncodeToString(addrHash[:]) + "0000000000000000000000000000000000000000000000000000000000000004" 2300 hb, err := hex.DecodeString(checkData) 2301 require.NoError(err) 2302 out2 := crypto.Keccak256(hb) 2303 ret, err := tr.Get(out2[:]) 2304 require.NoError(err) 2305 return big.NewInt(0).SetBytes(ret) 2306 } 2307 2308 func newChain(t *testing.T, stateTX bool) (blockchain.Blockchain, factory.Factory, db.KVStore, blockdao.BlockDAO, actpool.ActPool) { 2309 require := require.New(t) 2310 cfg := config.Default 2311 2312 testTriePath, err := testutil.PathOfTempFile("trie") 2313 require.NoError(err) 2314 testDBPath, err := testutil.PathOfTempFile("db") 2315 require.NoError(err) 2316 testIndexPath, err := testutil.PathOfTempFile("index") 2317 require.NoError(err) 2318 defer func() { 2319 testutil.CleanupPath(testTriePath) 2320 testutil.CleanupPath(testDBPath) 2321 testutil.CleanupPath(testIndexPath) 2322 }() 2323 2324 cfg.Chain.TrieDBPath = testTriePath 2325 cfg.Chain.ChainDBPath = testDBPath 2326 cfg.Chain.IndexDBPath = testIndexPath 2327 cfg.Chain.EnableArchiveMode = true 2328 cfg.Consensus.Scheme = config.RollDPoSScheme 2329 cfg.Genesis.BlockGasLimit = uint64(1000000) 2330 cfg.ActPool.MinGasPriceStr = "0" 2331 cfg.Genesis.EnableGravityChainVoting = false 2332 registry := protocol.NewRegistry() 2333 var sf factory.Factory 2334 kv := db.NewMemKVStore() 2335 factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis) 2336 if stateTX { 2337 sf, err = factory.NewStateDB(factoryCfg, kv, factory.RegistryStateDBOption(registry)) 2338 require.NoError(err) 2339 } else { 2340 sf, err = factory.NewFactory(factoryCfg, kv, factory.RegistryOption(registry)) 2341 require.NoError(err) 2342 } 2343 ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) 2344 require.NoError(err) 2345 acc := account.NewProtocol(rewarding.DepositGas) 2346 require.NoError(acc.Register(registry)) 2347 rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) 2348 require.NoError(rp.Register(registry)) 2349 var indexer blockindex.Indexer 2350 indexers := []blockdao.BlockIndexer{sf} 2351 if _, gateway := cfg.Plugins[config.GatewayPlugin]; gateway && !cfg.Chain.EnableAsyncIndexWrite { 2352 // create indexer 2353 cfg.DB.DbPath = cfg.Chain.IndexDBPath 2354 indexer, err = blockindex.NewIndexer(db.NewBoltDB(cfg.DB), cfg.Genesis.Hash()) 2355 require.NoError(err) 2356 indexers = append(indexers, indexer) 2357 } 2358 cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() 2359 // create BlockDAO 2360 cfg.DB.DbPath = cfg.Chain.ChainDBPath 2361 store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) 2362 require.NoError(err) 2363 dao := blockdao.NewBlockDAOWithIndexersAndCache(store, indexers, cfg.DB.MaxCacheSize) 2364 require.NotNil(dao) 2365 bc := blockchain.NewBlockchain( 2366 cfg.Chain, 2367 cfg.Genesis, 2368 dao, 2369 factory.NewMinter(sf, ap), 2370 blockchain.BlockValidatorOption(block.NewValidator( 2371 sf, 2372 protocol.NewGenericValidator(sf, accountutil.AccountState), 2373 )), 2374 ) 2375 require.NotNil(bc) 2376 ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, fakeGetBlockTime) 2377 require.NoError(ep.Register(registry)) 2378 require.NoError(bc.Start(context.Background())) 2379 2380 genesisPriKey := identityset.PrivateKey(27) 2381 a := identityset.Address(28).String() 2382 b := identityset.Address(29).String() 2383 // make a transfer from genesisAccount to a and b,because stateTX cannot store data in height 0 2384 tsf, err := action.SignedTransfer(a, genesisPriKey, 1, big.NewInt(100), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)) 2385 require.NoError(err) 2386 tsf2, err := action.SignedTransfer(b, genesisPriKey, 2, big.NewInt(100), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64)) 2387 require.NoError(err) 2388 require.NoError(ap.Add(context.Background(), tsf)) 2389 require.NoError(ap.Add(context.Background(), tsf2)) 2390 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 2391 require.NoError(err) 2392 require.NoError(bc.CommitBlock(blk)) 2393 return bc, sf, kv, dao, ap 2394 } 2395 2396 func makeTransfer(contract string, bc blockchain.Blockchain, ap actpool.ActPool, t *testing.T) *block.Block { 2397 require := require.New(t) 2398 genesisPriKey := identityset.PrivateKey(27) 2399 // make a transfer for contract,transfer 1 to io16eur00s9gdvak4ujhpuk9a45x24n60jgecgxzz 2400 bytecode, err := hex.DecodeString("a9059cbb0000000000000000000000004867c4bada9553216bf296c4c64e9ff0749206490000000000000000000000000000000000000000000000000000000000000001") 2401 require.NoError(err) 2402 execution, err := action.NewExecution(contract, 4, big.NewInt(0), 1000000, big.NewInt(testutil.TestGasPriceInt64), bytecode) 2403 require.NoError(err) 2404 bd := &action.EnvelopeBuilder{} 2405 elp := bd.SetAction(execution). 2406 SetNonce(4). 2407 SetGasLimit(1000000). 2408 SetGasPrice(big.NewInt(testutil.TestGasPriceInt64)).Build() 2409 selp, err := action.Sign(elp, genesisPriKey) 2410 require.NoError(err) 2411 require.NoError(ap.Add(context.Background(), selp)) 2412 blk, err := bc.MintNewBlock(testutil.TimestampNow()) 2413 require.NoError(err) 2414 require.NoError(bc.CommitBlock(blk)) 2415 return blk 2416 } 2417 2418 // classifyActions classfies actions 2419 func classifyActions(actions []*action.SealedEnvelope) ([]*action.Transfer, []*action.Execution) { 2420 tsfs := make([]*action.Transfer, 0) 2421 exes := make([]*action.Execution, 0) 2422 for _, elp := range actions { 2423 act := elp.Action() 2424 switch act := act.(type) { 2425 case *action.Transfer: 2426 tsfs = append(tsfs, act) 2427 case *action.Execution: 2428 exes = append(exes, act) 2429 } 2430 } 2431 return tsfs, exes 2432 } 2433 2434 func receiptByActionHash(dao blockdao.BlockDAO, height uint64, h hash.Hash256) (*action.Receipt, error) { 2435 receipts, err := dao.GetReceipts(height) 2436 if err != nil { 2437 return nil, err 2438 } 2439 for _, receipt := range receipts { 2440 if receipt.ActionHash == h { 2441 return receipt, nil 2442 } 2443 } 2444 return nil, errors.Errorf("failed to find receipt for %x", h) 2445 } 2446 2447 // TODO: add func TestValidateBlock()