-
Notifications
You must be signed in to change notification settings - Fork 320
/
generic_validator.go
67 lines (57 loc) · 2 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
// Copyright (c) 2019 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. 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(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(_ 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
confirmedState, err := v.accountState(v.sr, caller)
if err != nil {
return errors.Wrapf(err, "invalid state of account %s", caller.String())
}
pendingNonce := confirmedState.Nonce + 1
if selp.Nonce() > 0 && pendingNonce > selp.Nonce() {
return action.ErrNonceTooLow
}
return selp.Action().SanityCheck()
}