github.com/theQRL/go-zond@v0.1.1/zond/catalyst/simulated_beacon_test.go (about) 1 // Copyright 2023 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package catalyst 18 19 import ( 20 "context" 21 "math/big" 22 "testing" 23 "time" 24 25 "github.com/theQRL/go-zond/common" 26 "github.com/theQRL/go-zond/core" 27 "github.com/theQRL/go-zond/core/types" 28 "github.com/theQRL/go-zond/crypto" 29 "github.com/theQRL/go-zond/zond" 30 "github.com/theQRL/go-zond/zond/downloader" 31 "github.com/theQRL/go-zond/zond/ethconfig" 32 "github.com/theQRL/go-zond/node" 33 "github.com/theQRL/go-zond/p2p" 34 "github.com/theQRL/go-zond/params" 35 ) 36 37 func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node.Node, *eth.Ethereum, *SimulatedBeacon) { 38 t.Helper() 39 40 n, err := node.New(&node.Config{ 41 P2P: p2p.Config{ 42 ListenAddr: "127.0.0.1:8545", 43 NoDiscovery: true, 44 MaxPeers: 0, 45 }, 46 }) 47 if err != nil { 48 t.Fatal("can't create node:", err) 49 } 50 51 ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256} 52 ethservice, err := eth.New(n, ethcfg) 53 if err != nil { 54 t.Fatal("can't create eth service:", err) 55 } 56 57 simBeacon, err := NewSimulatedBeacon(1, ethservice) 58 if err != nil { 59 t.Fatal("can't create simulated beacon:", err) 60 } 61 62 n.RegisterLifecycle(simBeacon) 63 64 if err := n.Start(); err != nil { 65 t.Fatal("can't start node:", err) 66 } 67 68 ethservice.SetSynced() 69 return n, ethservice, simBeacon 70 } 71 72 // send 20 transactions, >10 withdrawals and ensure they are included in order 73 // send enough transactions to fill multiple blocks 74 func TestSimulatedBeaconSendWithdrawals(t *testing.T) { 75 var withdrawals []types.Withdrawal 76 txs := make(map[common.Hash]types.Transaction) 77 78 var ( 79 // testKey is a private key to use for funding a tester account. 80 testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 81 82 // testAddr is the Ethereum address of the tester account. 83 testAddr = crypto.PubkeyToAddress(testKey.PublicKey) 84 ) 85 86 // short period (1 second) for testing purposes 87 var gasLimit uint64 = 10_000_000 88 genesis := core.DeveloperGenesisBlock(gasLimit, testAddr) 89 node, ethService, mock := startSimulatedBeaconEthService(t, genesis) 90 _ = mock 91 defer node.Close() 92 93 chainHeadCh := make(chan core.ChainHeadEvent, 10) 94 subscription := ethService.BlockChain().SubscribeChainHeadEvent(chainHeadCh) 95 defer subscription.Unsubscribe() 96 97 // generate some withdrawals 98 for i := 0; i < 20; i++ { 99 withdrawals = append(withdrawals, types.Withdrawal{Index: uint64(i)}) 100 if err := mock.withdrawals.add(&withdrawals[i]); err != nil { 101 t.Fatal("addWithdrawal failed", err) 102 } 103 } 104 105 // generate a bunch of transactions 106 signer := types.NewEIP155Signer(ethService.BlockChain().Config().ChainID) 107 for i := 0; i < 20; i++ { 108 tx, err := types.SignTx(types.NewTransaction(uint64(i), common.Address{}, big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, testKey) 109 if err != nil { 110 t.Fatalf("error signing transaction, err=%v", err) 111 } 112 txs[tx.Hash()] = *tx 113 114 if err := ethService.APIBackend.SendTx(context.Background(), tx); err != nil { 115 t.Fatal("SendTx failed", err) 116 } 117 } 118 119 includedTxs := make(map[common.Hash]struct{}) 120 var includedWithdrawals []uint64 121 122 timer := time.NewTimer(12 * time.Second) 123 for { 124 select { 125 case evt := <-chainHeadCh: 126 for _, includedTx := range evt.Block.Transactions() { 127 includedTxs[includedTx.Hash()] = struct{}{} 128 } 129 for _, includedWithdrawal := range evt.Block.Withdrawals() { 130 includedWithdrawals = append(includedWithdrawals, includedWithdrawal.Index) 131 } 132 133 // ensure all withdrawals/txs included. this will take two blocks b/c number of withdrawals > 10 134 if len(includedTxs) == len(txs) && len(includedWithdrawals) == len(withdrawals) && evt.Block.Number().Cmp(big.NewInt(2)) == 0 { 135 return 136 } 137 case <-timer.C: 138 t.Fatal("timed out without including all withdrawals/txs") 139 } 140 } 141 }