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

     1  package sequencer
     2  
     3  import (
     4  	"math/big"
     5  	"time"
     6  
     7  	"github.com/0xPolygon/supernets2-node/log"
     8  	"github.com/0xPolygon/supernets2-node/state"
     9  	"github.com/ethereum/go-ethereum/common"
    10  	"github.com/ethereum/go-ethereum/core/types"
    11  )
    12  
    13  // TxTracker is a struct that contains all the tx data needed to be managed by the worker
    14  type TxTracker struct {
    15  	Hash                   common.Hash
    16  	HashStr                string
    17  	From                   common.Address
    18  	FromStr                string
    19  	Nonce                  uint64
    20  	Gas                    uint64 // To check if it fits into a batch
    21  	GasPrice               *big.Int
    22  	Cost                   *big.Int             // Cost = Amount + Benefit
    23  	Benefit                *big.Int             // GasLimit * GasPrice
    24  	BatchResources         state.BatchResources // To check if it fits into a batch
    25  	Efficiency             float64
    26  	RawTx                  []byte
    27  	ReceivedAt             time.Time // To check if it has been in the efficiency list for too long
    28  	IP                     string    // IP of the tx sender
    29  	FailedReason           *string   // FailedReason is the reason why the tx failed, if it failed
    30  	constraints            batchConstraintsFloat64
    31  	weightMultipliers      batchResourceWeightMultipliers
    32  	resourceCostMultiplier float64
    33  	totalWeight            float64
    34  }
    35  
    36  // batchResourceWeightMultipliers is a struct that contains the weight multipliers for each resource
    37  type batchResourceWeightMultipliers struct {
    38  	cumulativeGasUsed float64
    39  	arithmetics       float64
    40  	binaries          float64
    41  	keccakHashes      float64
    42  	memAligns         float64
    43  	poseidonHashes    float64
    44  	poseidonPaddings  float64
    45  	steps             float64
    46  	batchBytesSize    float64
    47  }
    48  
    49  // batchConstraints represents the constraints for a batch in float64
    50  type batchConstraintsFloat64 struct {
    51  	maxTxsPerBatch       float64
    52  	maxBatchBytesSize    float64
    53  	maxCumulativeGasUsed float64
    54  	maxKeccakHashes      float64
    55  	maxPoseidonHashes    float64
    56  	maxPoseidonPaddings  float64
    57  	maxMemAligns         float64
    58  	maxArithmetics       float64
    59  	maxBinaries          float64
    60  	maxSteps             float64
    61  }
    62  
    63  // newTxTracker creates and inti a TxTracker
    64  func newTxTracker(tx types.Transaction, counters state.ZKCounters, constraints batchConstraintsFloat64, weights batchResourceWeights, resourceCostMultiplier float64, ip string) (*TxTracker, error) {
    65  	addr, err := state.GetSender(tx)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	totalWeight := float64(weights.WeightArithmetics + weights.WeightBatchBytesSize + weights.WeightBinaries + weights.WeightCumulativeGasUsed +
    71  		weights.WeightKeccakHashes + weights.WeightMemAligns + weights.WeightPoseidonHashes + weights.WeightPoseidonPaddings + weights.WeightSteps)
    72  	rawTx, err := state.EncodeTransactions([]types.Transaction{tx})
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	txTracker := &TxTracker{
    77  		Hash:     tx.Hash(),
    78  		HashStr:  tx.Hash().String(),
    79  		From:     addr,
    80  		FromStr:  addr.String(),
    81  		Nonce:    tx.Nonce(),
    82  		Gas:      tx.Gas(),
    83  		GasPrice: tx.GasPrice(),
    84  		Cost:     tx.Cost(),
    85  		Benefit:  new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()),
    86  		BatchResources: state.BatchResources{
    87  			Bytes:      tx.Size(),
    88  			ZKCounters: counters,
    89  		},
    90  		Efficiency:             0,
    91  		RawTx:                  rawTx,
    92  		ReceivedAt:             time.Now(),
    93  		IP:                     ip,
    94  		constraints:            constraints,
    95  		weightMultipliers:      calculateWeightMultipliers(weights, totalWeight),
    96  		resourceCostMultiplier: resourceCostMultiplier,
    97  		totalWeight:            totalWeight,
    98  	}
    99  	txTracker.calculateEfficiency(constraints, weights)
   100  
   101  	return txTracker, nil
   102  }
   103  
   104  // updateZKCounters updates the counters of the tx and recalculates the tx efficiency
   105  
   106  func (tx *TxTracker) updateZKCounters(counters state.ZKCounters, constraints batchConstraintsFloat64, weights batchResourceWeights) {
   107  	tx.BatchResources.ZKCounters = counters
   108  	tx.calculateEfficiency(constraints, weights)
   109  }
   110  
   111  // calculateEfficiency calculates the tx efficiency
   112  func (tx *TxTracker) calculateEfficiency(constraints batchConstraintsFloat64, weights batchResourceWeights) {
   113  	totalWeight := float64(weights.WeightArithmetics + weights.WeightBatchBytesSize + weights.WeightBinaries + weights.WeightCumulativeGasUsed +
   114  		weights.WeightKeccakHashes + weights.WeightMemAligns + weights.WeightPoseidonHashes + weights.WeightPoseidonPaddings + weights.WeightSteps)
   115  
   116  	// TODO: Optmize tx.Efficiency calculation (precalculate constansts values)
   117  	// TODO: Evaluate avoid type conversion (performance impact?)
   118  	resourceCost := (float64(tx.BatchResources.ZKCounters.CumulativeGasUsed)/constraints.maxCumulativeGasUsed)*float64(weights.WeightCumulativeGasUsed)/totalWeight +
   119  		(float64(tx.BatchResources.ZKCounters.UsedArithmetics)/constraints.maxArithmetics)*float64(weights.WeightArithmetics)/totalWeight +
   120  		(float64(tx.BatchResources.ZKCounters.UsedBinaries)/constraints.maxBinaries)*float64(weights.WeightBinaries)/totalWeight +
   121  		(float64(tx.BatchResources.ZKCounters.UsedKeccakHashes)/constraints.maxKeccakHashes)*float64(weights.WeightKeccakHashes)/totalWeight +
   122  		(float64(tx.BatchResources.ZKCounters.UsedMemAligns)/constraints.maxMemAligns)*float64(weights.WeightMemAligns)/totalWeight +
   123  		(float64(tx.BatchResources.ZKCounters.UsedPoseidonHashes)/constraints.maxPoseidonHashes)*float64(weights.WeightPoseidonHashes)/totalWeight +
   124  		(float64(tx.BatchResources.ZKCounters.UsedPoseidonPaddings)/constraints.maxPoseidonPaddings)*float64(weights.WeightPoseidonPaddings)/totalWeight +
   125  		(float64(tx.BatchResources.ZKCounters.UsedSteps)/constraints.maxSteps)*float64(weights.WeightSteps)/totalWeight +
   126  		(float64(tx.BatchResources.Bytes)/constraints.maxBatchBytesSize)*float64(weights.WeightBatchBytesSize)/totalWeight //Meto config
   127  
   128  	resourceCost = resourceCost * tx.resourceCostMultiplier
   129  
   130  	var eff *big.Float
   131  
   132  	ben := big.NewFloat(0).SetInt(tx.Benefit)
   133  	rc := big.NewFloat(0).SetFloat64(resourceCost)
   134  	eff = big.NewFloat(0).Quo(ben, rc)
   135  
   136  	var accuracy big.Accuracy
   137  	tx.Efficiency, accuracy = eff.Float64()
   138  	log.Infof("CalculateEfficiency(%f) for tx(%s)", tx.Efficiency, tx.Hash.String())
   139  	if accuracy != big.Exact {
   140  		log.Errorf("CalculateEfficiency accuracy warning (%s). Calculated=%s Assigned=%f", accuracy.String(), eff.String(), tx.Efficiency)
   141  	}
   142  }
   143  
   144  // calculateWeightMultipliers calculates the weight multipliers for each resource
   145  func calculateWeightMultipliers(weights batchResourceWeights, totalWeight float64) batchResourceWeightMultipliers {
   146  	return batchResourceWeightMultipliers{
   147  		cumulativeGasUsed: float64(weights.WeightCumulativeGasUsed) / totalWeight,
   148  		arithmetics:       float64(weights.WeightArithmetics) / totalWeight,
   149  		binaries:          float64(weights.WeightBinaries) / totalWeight,
   150  		keccakHashes:      float64(weights.WeightKeccakHashes) / totalWeight,
   151  		memAligns:         float64(weights.WeightMemAligns) / totalWeight,
   152  		poseidonHashes:    float64(weights.WeightPoseidonHashes) / totalWeight,
   153  		poseidonPaddings:  float64(weights.WeightPoseidonPaddings) / totalWeight,
   154  		steps:             float64(weights.WeightSteps) / totalWeight,
   155  		batchBytesSize:    float64(weights.WeightBatchBytesSize) / totalWeight,
   156  	}
   157  }