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