github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/eventcheck/basiccheck/basic_check.go (about)

     1  package basiccheck
     2  
     3  import (
     4  	"errors"
     5  	"math"
     6  
     7  	base "github.com/unicornultrafoundation/go-helios/eventcheck/basiccheck"
     8  	"github.com/unicornultrafoundation/go-helios/hash"
     9  	"github.com/unicornultrafoundation/go-helios/native/idx"
    10  	"github.com/unicornultrafoundation/go-u2u/core/types"
    11  
    12  	"github.com/unicornultrafoundation/go-u2u/evmcore"
    13  	"github.com/unicornultrafoundation/go-u2u/native"
    14  )
    15  
    16  var (
    17  	ErrWrongNetForkID = errors.New("wrong network fork ID")
    18  	ErrZeroTime       = errors.New("event has zero timestamp")
    19  	ErrNegativeValue  = errors.New("negative value")
    20  	ErrIntrinsicGas   = errors.New("intrinsic gas too low")
    21  	// ErrTipAboveFeeCap is a sanity error to ensure no one is able to specify a
    22  	// transaction with a tip higher than the total fee cap.
    23  	ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas")
    24  	ErrWrongMP        = errors.New("inconsistent misbehaviour proof")
    25  	ErrNoCrimeInMP    = errors.New("action in misbehaviour proof isn't a criminal offence")
    26  	ErrWrongCreatorMP = errors.New("wrong creator in misbehaviour proof")
    27  	ErrMPTooLate      = errors.New("too old misbehaviour proof")
    28  	ErrMalformedMP    = errors.New("malformed MP union struct")
    29  	FutureBVsEpoch    = errors.New("future block votes epoch")
    30  	FutureEVEpoch     = errors.New("future epoch vote")
    31  	MalformedBVs      = errors.New("malformed BVs")
    32  	MalformedEV       = errors.New("malformed EV")
    33  	TooManyBVs        = errors.New("too many BVs")
    34  	EmptyEV           = errors.New("empty EV")
    35  	EmptyBVs          = errors.New("empty BVs")
    36  )
    37  
    38  const (
    39  	MaxBlockVotesPerEvent = 64
    40  	MaxLiableEpochs       = 32768
    41  )
    42  
    43  type Checker struct {
    44  	base base.Checker
    45  }
    46  
    47  // New validator which performs checks which don't require anything except event
    48  func New() *Checker {
    49  	return &Checker{
    50  		base: base.Checker{},
    51  	}
    52  }
    53  
    54  // validateTx checks whether a transaction is valid according to the consensus
    55  // rules
    56  func validateTx(tx *types.Transaction) error {
    57  	// Transactions can't be negative. This may never happen using RLP decoded
    58  	// transactions but may occur if you create a transaction using the RPC.
    59  	if tx.Value().Sign() < 0 || tx.GasPrice().Sign() < 0 {
    60  		return ErrNegativeValue
    61  	}
    62  	// Ensure the transaction has more gas than the basic tx fee.
    63  	intrGas, err := evmcore.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil)
    64  	if err != nil {
    65  		return err
    66  	}
    67  	if tx.Gas() < intrGas {
    68  		return ErrIntrinsicGas
    69  	}
    70  
    71  	if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 {
    72  		return ErrTipAboveFeeCap
    73  	}
    74  	return nil
    75  }
    76  
    77  func (v *Checker) validateMP(msgEpoch idx.Epoch, mp native.MisbehaviourProof) error {
    78  	count := 0
    79  	if proof := mp.EventsDoublesign; proof != nil {
    80  		count++
    81  		if err := v.validateEventLocator(proof.Pair[0].Locator); err != nil {
    82  			return err
    83  		}
    84  		if err := v.validateEventLocator(proof.Pair[1].Locator); err != nil {
    85  			return err
    86  		}
    87  		if proof.Pair[0].Locator.Creator != proof.Pair[1].Locator.Creator {
    88  			return ErrWrongCreatorMP
    89  		}
    90  		if proof.Pair[0].Locator.Epoch != proof.Pair[1].Locator.Epoch {
    91  			return ErrNoCrimeInMP
    92  		}
    93  		if proof.Pair[0].Locator.Seq != proof.Pair[1].Locator.Seq {
    94  			return ErrNoCrimeInMP
    95  		}
    96  		if proof.Pair[0].Locator == proof.Pair[1].Locator {
    97  			return ErrNoCrimeInMP
    98  		}
    99  		if msgEpoch > proof.Pair[0].Locator.Epoch+MaxLiableEpochs {
   100  			return ErrMPTooLate
   101  		}
   102  	}
   103  	if proof := mp.BlockVoteDoublesign; proof != nil {
   104  		count++
   105  		if err := v.ValidateBVs(proof.Pair[0]); err != nil {
   106  			return err
   107  		}
   108  		if err := v.ValidateBVs(proof.Pair[1]); err != nil {
   109  			return err
   110  		}
   111  		if proof.Pair[0].Signed.Locator.Creator != proof.Pair[1].Signed.Locator.Creator {
   112  			return ErrWrongCreatorMP
   113  		}
   114  		if proof.Block < proof.Pair[0].Val.Start || proof.Block >= proof.Pair[0].Val.Start+idx.Block(len(proof.Pair[0].Val.Votes)) {
   115  			return ErrWrongMP
   116  		}
   117  		if proof.Block < proof.Pair[1].Val.Start || proof.Block >= proof.Pair[1].Val.Start+idx.Block(len(proof.Pair[1].Val.Votes)) {
   118  			return ErrWrongMP
   119  		}
   120  		if proof.GetVote(0) == proof.GetVote(1) && proof.Pair[0].Val.Epoch == proof.Pair[1].Val.Epoch {
   121  			return ErrNoCrimeInMP
   122  		}
   123  		if msgEpoch > proof.Pair[0].Val.Epoch+MaxLiableEpochs || msgEpoch > proof.Pair[1].Val.Epoch+MaxLiableEpochs {
   124  			return ErrMPTooLate
   125  		}
   126  	}
   127  	if proof := mp.WrongBlockVote; proof != nil {
   128  		count++
   129  		for i, pal := range proof.Pals {
   130  			if err := v.ValidateBVs(pal); err != nil {
   131  				return err
   132  			}
   133  			if proof.Block < pal.Val.Start || proof.Block >= pal.Val.Start+idx.Block(len(pal.Val.Votes)) {
   134  				return ErrWrongMP
   135  			}
   136  			if msgEpoch > pal.Val.Epoch+MaxLiableEpochs {
   137  				return ErrMPTooLate
   138  			}
   139  			// see MinAccomplicesForProof
   140  			if proof.WrongEpoch {
   141  				if i > 0 && pal.Val.Epoch != proof.Pals[i-1].Val.Epoch {
   142  					return ErrNoCrimeInMP
   143  				}
   144  			} else {
   145  				if i > 0 && proof.GetVote(i-1) != proof.GetVote(i) {
   146  					return ErrNoCrimeInMP
   147  				}
   148  			}
   149  			for _, prev := range proof.Pals[:i] {
   150  				if prev.Signed.Locator.Creator == pal.Signed.Locator.Creator {
   151  					return ErrWrongCreatorMP
   152  				}
   153  			}
   154  		}
   155  	}
   156  	if proof := mp.EpochVoteDoublesign; proof != nil {
   157  		count++
   158  		if err := v.ValidateEV(proof.Pair[0]); err != nil {
   159  			return err
   160  		}
   161  		if err := v.ValidateEV(proof.Pair[1]); err != nil {
   162  			return err
   163  		}
   164  		if proof.Pair[0].Signed.Locator.Creator != proof.Pair[1].Signed.Locator.Creator {
   165  			return ErrWrongCreatorMP
   166  		}
   167  		if proof.Pair[0].Val.Epoch != proof.Pair[1].Val.Epoch {
   168  			return ErrNoCrimeInMP
   169  		}
   170  		if proof.Pair[0].Val.Vote == proof.Pair[1].Val.Vote {
   171  			return ErrNoCrimeInMP
   172  		}
   173  		if msgEpoch > proof.Pair[0].Val.Epoch+MaxLiableEpochs {
   174  			return ErrMPTooLate
   175  		}
   176  	}
   177  	if proof := mp.WrongEpochVote; proof != nil {
   178  		count++
   179  		for i, pal := range proof.Pals {
   180  			if err := v.ValidateEV(pal); err != nil {
   181  				return err
   182  			}
   183  			if msgEpoch > pal.Val.Epoch+MaxLiableEpochs {
   184  				return ErrMPTooLate
   185  			}
   186  			// see MinAccomplicesForProof
   187  			if i > 0 && proof.Pals[i-1].Val != proof.Pals[i].Val {
   188  				return ErrNoCrimeInMP
   189  			}
   190  			for _, prev := range proof.Pals[:i] {
   191  				if prev.Signed.Locator.Creator == pal.Signed.Locator.Creator {
   192  					return ErrWrongCreatorMP
   193  				}
   194  			}
   195  		}
   196  	}
   197  	if count != 1 {
   198  		return ErrMalformedMP
   199  	}
   200  	return nil
   201  }
   202  
   203  func (v *Checker) checkTxs(e native.EventPayloadI) error {
   204  	for _, tx := range e.Txs() {
   205  		if err := validateTx(tx); err != nil {
   206  			return err
   207  		}
   208  	}
   209  	return nil
   210  }
   211  
   212  // Validate event
   213  func (v *Checker) Validate(e native.EventPayloadI) error {
   214  	if e.NetForkID() != 0 {
   215  		return ErrWrongNetForkID
   216  	}
   217  	if err := v.base.Validate(e); err != nil {
   218  		return err
   219  	}
   220  	if e.GasPowerUsed() >= math.MaxInt64-1 || e.GasPowerLeft().Max() >= math.MaxInt64-1 {
   221  		return base.ErrHugeValue
   222  	}
   223  	if e.CreationTime() <= 0 || e.MedianTime() <= 0 {
   224  		return ErrZeroTime
   225  	}
   226  	if err := v.checkTxs(e); err != nil {
   227  		return err
   228  	}
   229  	for _, mp := range e.MisbehaviourProofs() {
   230  		if err := v.validateMP(e.Epoch(), mp); err != nil {
   231  			return err
   232  		}
   233  	}
   234  	if err := v.validateEV(e.Epoch(), e.EpochVote(), false); err != nil {
   235  		return err
   236  	}
   237  	if err := v.validateBVs(e.Epoch(), e.BlockVotes(), false); err != nil {
   238  		return err
   239  	}
   240  
   241  	return nil
   242  }
   243  
   244  func (v *Checker) validateEventLocator(e native.EventLocator) error {
   245  	if e.NetForkID != 0 {
   246  		return ErrWrongNetForkID
   247  	}
   248  	if e.Seq >= math.MaxInt32-1 || e.Epoch >= math.MaxInt32-1 ||
   249  		e.Lamport >= math.MaxInt32-1 {
   250  		return base.ErrHugeValue
   251  	}
   252  	return nil
   253  }
   254  
   255  func (v *Checker) validateBVs(eventEpoch idx.Epoch, bvs native.LlrBlockVotes, greedy bool) error {
   256  	if bvs.Epoch > eventEpoch {
   257  		return FutureBVsEpoch
   258  	}
   259  	if bvs.Start >= math.MaxInt64/2 {
   260  		return base.ErrHugeValue
   261  	}
   262  	if bvs.Epoch >= math.MaxInt32-1 {
   263  		return base.ErrHugeValue
   264  	}
   265  	if len(bvs.Votes) > MaxBlockVotesPerEvent {
   266  		return TooManyBVs
   267  	}
   268  	if ((bvs.Start == 0) != (len(bvs.Votes) == 0)) || ((bvs.Start == 0) != (bvs.Epoch == 0)) {
   269  		return MalformedBVs
   270  	}
   271  
   272  	if greedy && bvs.Epoch == 0 {
   273  		return EmptyBVs
   274  	}
   275  	return nil
   276  }
   277  
   278  func (v *Checker) validateEV(eventEpoch idx.Epoch, ev native.LlrEpochVote, greedy bool) error {
   279  	if ev.Epoch > eventEpoch {
   280  		return FutureEVEpoch
   281  	}
   282  	if (ev.Epoch == 0) != (ev.Vote == hash.Zero) {
   283  		return MalformedEV
   284  	}
   285  	if ev.Epoch >= math.MaxInt32-1 {
   286  		return base.ErrHugeValue
   287  	}
   288  	if greedy && ev.Epoch == 0 {
   289  		return EmptyEV
   290  	}
   291  	return nil
   292  }
   293  
   294  func (v *Checker) ValidateBVs(bvs native.LlrSignedBlockVotes) error {
   295  	if err := v.validateEventLocator(bvs.Signed.Locator); err != nil {
   296  		return err
   297  	}
   298  	return v.validateBVs(bvs.Signed.Locator.Epoch, bvs.Val, true)
   299  }
   300  
   301  func (v *Checker) ValidateEV(ev native.LlrSignedEpochVote) error {
   302  	if err := v.validateEventLocator(ev.Signed.Locator); err != nil {
   303  		return err
   304  	}
   305  	return v.validateEV(ev.Signed.Locator.Epoch, ev.Val, true)
   306  }