github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/sequencer/worker_test.go (about)

     1  package sequencer
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/big"
     7  	"testing"
     8  
     9  	"github.com/0xPolygon/supernets2-node/state"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  var (
    15  	workerCfg = WorkerCfg{
    16  		ResourceCostMultiplier: 1000,
    17  	}
    18  )
    19  
    20  type workerAddTxTestCase struct {
    21  	name   string
    22  	from   common.Address
    23  	txHash common.Hash
    24  	nonce  uint64
    25  	// isClaim                bool
    26  	benefit                int64
    27  	cost                   *big.Int
    28  	counters               state.ZKCounters
    29  	usedBytes              uint64
    30  	expectedEfficiencyList []common.Hash
    31  }
    32  
    33  type workerAddrQueueInfo struct {
    34  	from    common.Address
    35  	nonce   *big.Int
    36  	balance *big.Int
    37  }
    38  
    39  func processWorkerAddTxTestCases(t *testing.T, worker *Worker, testCases []workerAddTxTestCase) {
    40  	totalWeight := float64(worker.batchResourceWeights.WeightArithmetics +
    41  		worker.batchResourceWeights.WeightBatchBytesSize + worker.batchResourceWeights.WeightBinaries +
    42  		worker.batchResourceWeights.WeightCumulativeGasUsed + worker.batchResourceWeights.WeightKeccakHashes +
    43  		worker.batchResourceWeights.WeightMemAligns + worker.batchResourceWeights.WeightPoseidonHashes +
    44  		worker.batchResourceWeights.WeightPoseidonPaddings + worker.batchResourceWeights.WeightSteps)
    45  
    46  	for _, testCase := range testCases {
    47  		t.Run(testCase.name, func(t *testing.T) {
    48  			tx := TxTracker{}
    49  
    50  			tx.weightMultipliers = calculateWeightMultipliers(worker.batchResourceWeights, totalWeight)
    51  			tx.constraints = worker.batchConstraints
    52  			tx.resourceCostMultiplier = worker.cfg.ResourceCostMultiplier
    53  			tx.Hash = testCase.txHash
    54  			tx.HashStr = testCase.txHash.String()
    55  			tx.From = testCase.from
    56  			tx.FromStr = testCase.from.String()
    57  			tx.Nonce = testCase.nonce
    58  			tx.Benefit = new(big.Int).SetInt64(testCase.benefit)
    59  			tx.Cost = testCase.cost
    60  			tx.BatchResources.Bytes = testCase.usedBytes
    61  			tx.updateZKCounters(testCase.counters, worker.batchConstraints, worker.batchResourceWeights)
    62  			t.Logf("%s=%s", testCase.name, fmt.Sprintf("%.2f", tx.Efficiency))
    63  
    64  			err, _ := worker.AddTxTracker(ctx, &tx)
    65  			if err != nil {
    66  				return
    67  			}
    68  
    69  			el := worker.efficiencyList
    70  			if el.len() != len(testCase.expectedEfficiencyList) {
    71  				t.Fatalf("Error efficiencylist.len(%d) != expectedEfficiencyList.len(%d)", el.len(), len(testCase.expectedEfficiencyList))
    72  			}
    73  			for i := 0; i < el.len(); i++ {
    74  				if el.getByIndex(i).HashStr != string(testCase.expectedEfficiencyList[i].String()) {
    75  					t.Fatalf("Error efficiencylist(%d). Expected=%s, Actual=%s", i, testCase.expectedEfficiencyList[i].String(), el.getByIndex(i).HashStr)
    76  				}
    77  			}
    78  		})
    79  	}
    80  }
    81  
    82  func TestWorkerAddTx(t *testing.T) {
    83  	var nilErr error
    84  
    85  	// Init ZKEVM resourceCostWeight values
    86  	rcWeigth := batchResourceWeights{}
    87  	rcWeigth.WeightCumulativeGasUsed = 1
    88  	rcWeigth.WeightArithmetics = 1
    89  	rcWeigth.WeightBinaries = 1
    90  	rcWeigth.WeightKeccakHashes = 1
    91  	rcWeigth.WeightMemAligns = 1
    92  	rcWeigth.WeightPoseidonHashes = 1
    93  	rcWeigth.WeightPoseidonPaddings = 1
    94  	rcWeigth.WeightSteps = 1
    95  	rcWeigth.WeightBatchBytesSize = 2
    96  
    97  	// Init ZKEVM resourceCostMax values
    98  	rcMax := batchConstraints{}
    99  	rcMax.MaxCumulativeGasUsed = 10
   100  	rcMax.MaxArithmetics = 10
   101  	rcMax.MaxBinaries = 10
   102  	rcMax.MaxKeccakHashes = 10
   103  	rcMax.MaxMemAligns = 10
   104  	rcMax.MaxPoseidonHashes = 10
   105  	rcMax.MaxPoseidonPaddings = 10
   106  	rcMax.MaxSteps = 10
   107  	rcMax.MaxBatchBytesSize = 10
   108  
   109  	stateMock := NewStateMock(t)
   110  	worker := initWorker(stateMock, rcMax, rcWeigth)
   111  
   112  	ctx := context.Background()
   113  
   114  	stateMock.On("GetLastStateRoot", ctx, nil).Return(common.Hash{0}, nilErr)
   115  
   116  	addrQueueInfo := []workerAddrQueueInfo{
   117  		{from: common.Address{1}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   118  		{from: common.Address{2}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   119  		{from: common.Address{3}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   120  		{from: common.Address{4}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   121  	}
   122  
   123  	for _, aq := range addrQueueInfo {
   124  		stateMock.On("GetNonceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.nonce, nilErr)
   125  		stateMock.On("GetBalanceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.balance, nilErr)
   126  	}
   127  
   128  	addTxsTC := []workerAddTxTestCase{
   129  		{
   130  			name: "Adding from:0x01, tx:0x01/ef:10", from: common.Address{1}, txHash: common.Hash{1}, nonce: 1,
   131  			benefit: 1000, cost: new(big.Int).SetInt64(5),
   132  			counters:  state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1},
   133  			usedBytes: 1,
   134  			expectedEfficiencyList: []common.Hash{
   135  				{1},
   136  			},
   137  		},
   138  		{
   139  			name: "Adding from:0x02, tx:0x02/ef:20", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1,
   140  			benefit: 2000, cost: new(big.Int).SetInt64(5),
   141  			counters:  state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1},
   142  			usedBytes: 1,
   143  			expectedEfficiencyList: []common.Hash{
   144  				{2}, {1},
   145  			},
   146  		},
   147  		{
   148  			name: "Readding from:0x02, tx:0x02/ef:4", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1,
   149  			benefit: 2000, cost: new(big.Int).SetInt64(5),
   150  			counters:  state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5},
   151  			usedBytes: 5,
   152  			expectedEfficiencyList: []common.Hash{
   153  				{1}, {2},
   154  			},
   155  		},
   156  		{
   157  			name: "Readding from:0x03, tx:0x03/ef:25", from: common.Address{3}, txHash: common.Hash{3}, nonce: 1,
   158  			benefit: 5000, cost: new(big.Int).SetInt64(5),
   159  			counters:  state.ZKCounters{CumulativeGasUsed: 2, UsedKeccakHashes: 2, UsedPoseidonHashes: 2, UsedPoseidonPaddings: 2, UsedMemAligns: 2, UsedArithmetics: 2, UsedBinaries: 2, UsedSteps: 2},
   160  			usedBytes: 2,
   161  			expectedEfficiencyList: []common.Hash{
   162  				{3}, {1}, {2},
   163  			},
   164  		},
   165  	}
   166  
   167  	processWorkerAddTxTestCases(t, worker, addTxsTC)
   168  
   169  	// Change counters fpr tx:0x03/ef:9.61
   170  	counters := state.ZKCounters{CumulativeGasUsed: 6, UsedKeccakHashes: 6, UsedPoseidonHashes: 6, UsedPoseidonPaddings: 6, UsedMemAligns: 6, UsedArithmetics: 6, UsedBinaries: 6, UsedSteps: 6}
   171  	worker.UpdateTx(common.Hash{3}, common.Address{3}, counters)
   172  
   173  	addTxsTC = []workerAddTxTestCase{
   174  		{
   175  			name: "Adding from:0x04, tx:0x04/ef:100", from: common.Address{4}, txHash: common.Hash{4}, nonce: 1,
   176  			benefit: 10000, cost: new(big.Int).SetInt64(5),
   177  			counters:  state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1},
   178  			usedBytes: 1,
   179  			expectedEfficiencyList: []common.Hash{
   180  				{4}, {1}, {3}, {2},
   181  			},
   182  		},
   183  	}
   184  
   185  	processWorkerAddTxTestCases(t, worker, addTxsTC)
   186  }
   187  
   188  func TestWorkerGetBestTx(t *testing.T) {
   189  	var nilErr error
   190  
   191  	// Init ZKEVM resourceCostWeight values
   192  	rcWeight := batchResourceWeights{}
   193  	rcWeight.WeightCumulativeGasUsed = 1
   194  	rcWeight.WeightArithmetics = 1
   195  	rcWeight.WeightBinaries = 1
   196  	rcWeight.WeightKeccakHashes = 1
   197  	rcWeight.WeightMemAligns = 1
   198  	rcWeight.WeightPoseidonHashes = 1
   199  	rcWeight.WeightPoseidonPaddings = 1
   200  	rcWeight.WeightSteps = 1
   201  	rcWeight.WeightBatchBytesSize = 2
   202  
   203  	// Init ZKEVM resourceCostMax values
   204  	rcMax := batchConstraints{}
   205  	rcMax.MaxCumulativeGasUsed = 10
   206  	rcMax.MaxArithmetics = 10
   207  	rcMax.MaxBinaries = 10
   208  	rcMax.MaxKeccakHashes = 10
   209  	rcMax.MaxMemAligns = 10
   210  	rcMax.MaxPoseidonHashes = 10
   211  	rcMax.MaxPoseidonPaddings = 10
   212  	rcMax.MaxSteps = 10
   213  	rcMax.MaxBatchBytesSize = 10
   214  
   215  	rc := state.BatchResources{
   216  		ZKCounters: state.ZKCounters{CumulativeGasUsed: 10, UsedKeccakHashes: 10, UsedPoseidonHashes: 10, UsedPoseidonPaddings: 10, UsedMemAligns: 10, UsedArithmetics: 10, UsedBinaries: 10, UsedSteps: 10},
   217  		Bytes:      10,
   218  	}
   219  
   220  	stateMock := NewStateMock(t)
   221  	worker := initWorker(stateMock, rcMax, rcWeight)
   222  
   223  	ctx := context.Background()
   224  
   225  	stateMock.On("GetLastStateRoot", ctx, nil).Return(common.Hash{0}, nilErr)
   226  
   227  	addrQueueInfo := []workerAddrQueueInfo{
   228  		{from: common.Address{1}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   229  		{from: common.Address{2}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   230  		{from: common.Address{3}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   231  		{from: common.Address{4}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)},
   232  	}
   233  
   234  	for _, aq := range addrQueueInfo {
   235  		stateMock.On("GetNonceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.nonce, nilErr)
   236  		stateMock.On("GetBalanceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.balance, nilErr)
   237  	}
   238  
   239  	addTxsTC := []workerAddTxTestCase{
   240  		{
   241  			name: "Adding from:0x01, tx:0x01/ef:10", from: common.Address{1}, txHash: common.Hash{1}, nonce: 1,
   242  			benefit: 1000, cost: new(big.Int).SetInt64(5),
   243  			counters:  state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1},
   244  			usedBytes: 1,
   245  			expectedEfficiencyList: []common.Hash{
   246  				{1},
   247  			},
   248  		},
   249  		{
   250  			name: "Adding from:0x02, tx:0x02/ef:12", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1,
   251  			benefit: 6000, cost: new(big.Int).SetInt64(5),
   252  			counters:  state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5},
   253  			usedBytes: 5,
   254  			expectedEfficiencyList: []common.Hash{
   255  				{2}, {1},
   256  			},
   257  		},
   258  		{
   259  			name: "Readding from:0x03, tx:0x03/ef:25", from: common.Address{3}, txHash: common.Hash{3}, nonce: 1,
   260  			benefit: 5000, cost: new(big.Int).SetInt64(5),
   261  			counters:  state.ZKCounters{CumulativeGasUsed: 2, UsedKeccakHashes: 2, UsedPoseidonHashes: 2, UsedPoseidonPaddings: 2, UsedMemAligns: 2, UsedArithmetics: 2, UsedBinaries: 2, UsedSteps: 2},
   262  			usedBytes: 2,
   263  			expectedEfficiencyList: []common.Hash{
   264  				{3}, {2}, {1},
   265  			},
   266  		},
   267  		{
   268  			name: "Adding from:0x04, tx:0x04/ef:100", from: common.Address{4}, txHash: common.Hash{4}, nonce: 1,
   269  			benefit: 40000, cost: new(big.Int).SetInt64(5),
   270  			counters:  state.ZKCounters{CumulativeGasUsed: 4, UsedKeccakHashes: 4, UsedPoseidonHashes: 4, UsedPoseidonPaddings: 4, UsedMemAligns: 4, UsedArithmetics: 4, UsedBinaries: 4, UsedSteps: 4},
   271  			usedBytes: 4,
   272  			expectedEfficiencyList: []common.Hash{
   273  				{4}, {3}, {2}, {1},
   274  			},
   275  		},
   276  	}
   277  
   278  	processWorkerAddTxTestCases(t, worker, addTxsTC)
   279  
   280  	expectedGetBestTx := []common.Hash{{4}, {3}, {1}}
   281  	ct := 0
   282  
   283  	for {
   284  		tx := worker.GetBestFittingTx(rc)
   285  		if tx != nil {
   286  			if ct >= len(expectedGetBestTx) {
   287  				t.Fatalf("Error getting more best tx than expected. Expected=%d, Actual=%d", len(expectedGetBestTx), ct+1)
   288  			}
   289  			if tx.HashStr != string(expectedGetBestTx[ct].String()) {
   290  				t.Fatalf("Error GetBestFittingTx(%d). Expected=%s, Actual=%s", ct, expectedGetBestTx[ct].String(), tx.HashStr)
   291  			}
   292  			err := rc.Sub(tx.BatchResources)
   293  			assert.NoError(t, err)
   294  
   295  			touch := make(map[common.Address]*state.InfoReadWrite)
   296  			var newNonce uint64 = tx.Nonce + 1
   297  			touch[tx.From] = &state.InfoReadWrite{Address: tx.From, Nonce: &newNonce, Balance: new(big.Int).SetInt64(10)}
   298  			worker.UpdateAfterSingleSuccessfulTxExecution(tx.From, touch)
   299  			ct++
   300  		} else {
   301  			if ct < len(expectedGetBestTx) {
   302  				t.Fatalf("Error expecting more best tx. Expected=%d, Actual=%d", len(expectedGetBestTx), ct)
   303  			}
   304  			break
   305  		}
   306  	}
   307  }
   308  
   309  func initWorker(stateMock *StateMock, rcMax batchConstraints, rcWeigth batchResourceWeights) *Worker {
   310  	worker := NewWorker(workerCfg, stateMock, rcMax, rcWeigth)
   311  	return worker
   312  }