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  }