github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/ci/e2e-group10/forced_batches_test.go (about) 1 package e2e 2 3 import ( 4 "context" 5 "math/big" 6 "testing" 7 "time" 8 9 "github.com/ethereum/go-ethereum/core/types" 10 11 "github.com/0xPolygon/supernets2-node/etherman/smartcontracts/polygonzkevmglobalexitroot" 12 "github.com/0xPolygon/supernets2-node/etherman/smartcontracts/supernets2" 13 "github.com/0xPolygon/supernets2-node/log" 14 "github.com/0xPolygon/supernets2-node/state" 15 "github.com/0xPolygon/supernets2-node/test/constants" 16 "github.com/0xPolygon/supernets2-node/test/operations" 17 "github.com/ethereum/go-ethereum" 18 "github.com/ethereum/go-ethereum/accounts/abi/bind" 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/ethclient" 21 "github.com/stretchr/testify/require" 22 ) 23 24 const ( 25 toAddressHex = "0x4d5Cf5032B2a844602278b01199ED191A86c93ff" 26 gerFinalityBlocks = uint64(250) 27 ) 28 29 var ( 30 toAddress = common.HexToAddress(toAddressHex) 31 ) 32 33 func TestForcedBatches(t *testing.T) { 34 if testing.Short() { 35 t.Skip() 36 } 37 38 defer func() { 39 require.NoError(t, operations.Teardown()) 40 }() 41 42 var err error 43 nTxs := 10 44 ctx := context.Background() 45 opsman, auth, client, amount, gasLimit, gasPrice, nonce := setupEnvironment(ctx, t) 46 47 txs := make([]*types.Transaction, 0, nTxs) 48 for i := 0; i < nTxs; i++ { 49 tx := types.NewTransaction(nonce, toAddress, amount, gasLimit, gasPrice, nil) 50 nonce = nonce + 1 51 txs = append(txs, tx) 52 } 53 54 var l2BlockNumbers []*big.Int 55 l2BlockNumbers, err = operations.ApplyL2Txs(ctx, txs, auth, client, operations.VerifiedConfirmationLevel) 56 require.NoError(t, err) 57 58 time.Sleep(2 * time.Second) 59 amount = big.NewInt(0).Add(amount, big.NewInt(10)) 60 unsignedTx := types.NewTransaction(nonce, toAddress, amount, gasLimit, gasPrice, nil) 61 signedTx, err := auth.Signer(auth.From, unsignedTx) 62 require.NoError(t, err) 63 encodedTxs, err := state.EncodeTransactions([]types.Transaction{*signedTx}) 64 require.NoError(t, err) 65 forcedBatch, err := sendForcedBatch(t, encodedTxs, opsman) 66 require.NoError(t, err) 67 68 // Checking if all txs sent before the forced batch were processed within previous closed batch 69 for _, l2blockNum := range l2BlockNumbers { 70 batch, err := opsman.State().GetBatchByL2BlockNumber(ctx, l2blockNum.Uint64(), nil) 71 require.NoError(t, err) 72 require.Less(t, batch.BatchNumber, forcedBatch.BatchNumber) 73 } 74 } 75 76 func setupEnvironment(ctx context.Context, t *testing.T) (*operations.Manager, *bind.TransactOpts, *ethclient.Client, *big.Int, uint64, *big.Int, uint64) { 77 78 err := operations.Teardown() 79 require.NoError(t, err) 80 opsCfg := operations.GetDefaultOperationsConfig() 81 opsCfg.State.MaxCumulativeGasUsed = 80000000000 82 opsman, err := operations.NewManager(ctx, opsCfg) 83 require.NoError(t, err) 84 err = opsman.Setup() 85 require.NoError(t, err) 86 time.Sleep(5 * time.Second) 87 // Load account with balance on local genesis 88 auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) 89 require.NoError(t, err) 90 // Load eth client 91 client, err := ethclient.Dial(operations.DefaultL2NetworkURL) 92 require.NoError(t, err) 93 // Send txs 94 amount := big.NewInt(10000) 95 senderBalance, err := client.BalanceAt(ctx, auth.From, nil) 96 require.NoError(t, err) 97 senderNonce, err := client.PendingNonceAt(ctx, auth.From) 98 require.NoError(t, err) 99 100 log.Infof("Receiver Addr: %v", toAddress.String()) 101 log.Infof("Sender Addr: %v", auth.From.String()) 102 log.Infof("Sender Balance: %v", senderBalance.String()) 103 log.Infof("Sender Nonce: %v", senderNonce) 104 105 gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{From: auth.From, To: &toAddress, Value: amount}) 106 require.NoError(t, err) 107 108 gasPrice, err := client.SuggestGasPrice(ctx) 109 require.NoError(t, err) 110 111 nonce, err := client.PendingNonceAt(ctx, auth.From) 112 require.NoError(t, err) 113 return opsman, auth, client, amount, gasLimit, gasPrice, nonce 114 } 115 116 func sendForcedBatch(t *testing.T, txs []byte, opsman *operations.Manager) (*state.Batch, error) { 117 ctx := context.Background() 118 st := opsman.State() 119 // Connect to ethereum node 120 ethClient, err := ethclient.Dial(operations.DefaultL1NetworkURL) 121 require.NoError(t, err) 122 123 initialGer, _, err := st.GetLatestGer(ctx, gerFinalityBlocks) 124 require.NoError(t, err) 125 126 // Create smc client 127 supernets2Addr := common.HexToAddress(operations.DefaultL1Supernets2SmartContract) 128 supernets2, err := supernets2.NewSupernets2(supernets2Addr, ethClient) 129 require.NoError(t, err) 130 131 auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) 132 require.NoError(t, err) 133 134 log.Info("Using address: ", auth.From) 135 136 num, err := supernets2.LastForceBatch(&bind.CallOpts{Pending: false}) 137 require.NoError(t, err) 138 139 log.Info("Number of forceBatches in the smc: ", num) 140 141 // Get tip 142 tip, err := supernets2.GetForcedBatchFee(&bind.CallOpts{Pending: false}) 143 require.NoError(t, err) 144 145 managerAddress, err := supernets2.GlobalExitRootManager(&bind.CallOpts{Pending: false}) 146 require.NoError(t, err) 147 148 manager, err := polygonzkevmglobalexitroot.NewPolygonzkevmglobalexitroot(managerAddress, ethClient) 149 require.NoError(t, err) 150 151 rootInContract, err := manager.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) 152 require.NoError(t, err) 153 rootInContractHash := common.BytesToHash(rootInContract[:]) 154 155 disallowed, err := supernets2.IsForcedBatchDisallowed(&bind.CallOpts{Pending: false}) 156 require.NoError(t, err) 157 if disallowed { 158 tx, err := supernets2.ActivateForceBatches(auth) 159 require.NoError(t, err) 160 err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) 161 require.NoError(t, err) 162 } 163 164 currentBlock, err := ethClient.BlockByNumber(ctx, nil) 165 require.NoError(t, err) 166 167 log.Debug("currentBlock.Time(): ", currentBlock.Time()) 168 169 // Send forceBatch 170 tx, err := supernets2.ForceBatch(auth, txs, tip) 171 require.NoError(t, err) 172 173 log.Info("TxHash: ", tx.Hash()) 174 time.Sleep(1 * time.Second) 175 176 err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) 177 require.NoError(t, err) 178 179 query := ethereum.FilterQuery{ 180 FromBlock: currentBlock.Number(), 181 Addresses: []common.Address{supernets2Addr}, 182 } 183 logs, err := ethClient.FilterLogs(ctx, query) 184 require.NoError(t, err) 185 186 var forcedBatch *state.Batch 187 for _, vLog := range logs { 188 if vLog.Topics[0] != constants.ForcedBatchSignatureHash { 189 logs, err = ethClient.FilterLogs(ctx, query) 190 require.NoError(t, err) 191 continue 192 } 193 fb, err := supernets2.ParseForceBatch(vLog) 194 if err != nil { 195 log.Errorf("failed to parse force batch log event, err: ", err) 196 } 197 log.Debugf("log decoded: %+v", fb) 198 ger := fb.LastGlobalExitRoot 199 log.Info("GlobalExitRoot: ", ger) 200 log.Info("Transactions: ", common.Bytes2Hex(fb.Transactions)) 201 fullBlock, err := ethClient.BlockByHash(ctx, vLog.BlockHash) 202 if err != nil { 203 log.Errorf("error getting hashParent. BlockNumber: %d. Error: %v", vLog.BlockNumber, err) 204 return nil, err 205 } 206 log.Info("MinForcedTimestamp: ", fullBlock.Time()) 207 forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) 208 for err == state.ErrStateNotSynchronized { 209 time.Sleep(1 * time.Second) 210 forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) 211 } 212 log.Info("ForcedBatchNum: ", forcedBatch.BatchNumber) 213 require.NoError(t, err) 214 require.NotNil(t, forcedBatch) 215 216 log.Info("Waiting for batch to be virtualized...") 217 err = operations.WaitBatchToBeVirtualized(forcedBatch.BatchNumber, 4*time.Minute, st) 218 require.NoError(t, err) 219 220 log.Info("Waiting for batch to be consolidated...") 221 err = operations.WaitBatchToBeConsolidated(forcedBatch.BatchNumber, 4*time.Minute, st) 222 require.NoError(t, err) 223 224 if rootInContractHash != initialGer.GlobalExitRoot { 225 finalGer, _, err := st.GetLatestGer(ctx, gerFinalityBlocks) 226 require.NoError(t, err) 227 if finalGer.GlobalExitRoot != rootInContractHash { 228 log.Fatal("global exit root is not updated") 229 } 230 } 231 } 232 233 return forcedBatch, nil 234 }