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 }