github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/generic_validator.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package protocol 7 8 import ( 9 "context" 10 11 "github.com/pkg/errors" 12 13 "github.com/iotexproject/iotex-address/address" 14 15 "github.com/iotexproject/iotex-core/action" 16 "github.com/iotexproject/iotex-core/state" 17 ) 18 19 type ( 20 // AccountState defines a function to return the account state of a given address 21 AccountState func(context.Context, StateReader, address.Address) (*state.Account, error) 22 // GenericValidator is the validator for generic action verification 23 GenericValidator struct { 24 accountState AccountState 25 sr StateReader 26 } 27 ) 28 29 // NewGenericValidator constructs a new genericValidator 30 func NewGenericValidator(sr StateReader, accountState AccountState) *GenericValidator { 31 return &GenericValidator{ 32 sr: sr, 33 accountState: accountState, 34 } 35 } 36 37 // Validate validates a generic action 38 func (v *GenericValidator) Validate(ctx context.Context, selp *action.SealedEnvelope) error { 39 intrinsicGas, err := selp.IntrinsicGas() 40 if err != nil { 41 return err 42 } 43 if intrinsicGas > selp.GasLimit() { 44 return action.ErrIntrinsicGas 45 } 46 47 // Verify action using action sender's public key 48 if err := selp.VerifySignature(); err != nil { 49 return err 50 } 51 caller := selp.SenderAddress() 52 if caller == nil { 53 return errors.New("failed to get address") 54 } 55 // Reject action if nonce is too low 56 if action.IsSystemAction(selp) { 57 if selp.Nonce() != 0 { 58 return action.ErrSystemActionNonce 59 } 60 } else { 61 var ( 62 nonce uint64 63 featureCtx, ok = GetFeatureCtx(ctx) 64 ) 65 if ok && featureCtx.FixGasAndNonceUpdate || selp.Nonce() != 0 { 66 confirmedState, err := v.accountState(ctx, v.sr, caller) 67 if err != nil { 68 return errors.Wrapf(err, "invalid state of account %s", caller.String()) 69 } 70 if featureCtx.UseZeroNonceForFreshAccount { 71 nonce = confirmedState.PendingNonceConsideringFreshAccount() 72 } else { 73 nonce = confirmedState.PendingNonce() 74 } 75 if nonce > selp.Nonce() { 76 return action.ErrNonceTooLow 77 } 78 } 79 } 80 81 return selp.Action().SanityCheck() 82 }