forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 6
/
default_validation.go
150 lines (130 loc) · 4.97 KB
/
default_validation.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package builtin
import (
"fmt"
"reflect"
"github.com/hyperledger/fabric-protos-go/common"
commonerrors "github.com/hyperledger/fabric/common/errors"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/core/committer/txvalidator/v20/plugindispatcher"
validation "github.com/hyperledger/fabric/core/handlers/validation/api"
. "github.com/hyperledger/fabric/core/handlers/validation/api/capabilities"
. "github.com/hyperledger/fabric/core/handlers/validation/api/identities"
. "github.com/hyperledger/fabric/core/handlers/validation/api/policies"
. "github.com/hyperledger/fabric/core/handlers/validation/api/state"
v12 "github.com/hyperledger/fabric/core/handlers/validation/builtin/v12"
v13 "github.com/hyperledger/fabric/core/handlers/validation/builtin/v13"
v20 "github.com/hyperledger/fabric/core/handlers/validation/builtin/v20"
"github.com/pkg/errors"
)
var logger = flogging.MustGetLogger("vscc")
type DefaultValidationFactory struct {
}
func (*DefaultValidationFactory) New() validation.Plugin {
return &DefaultValidation{}
}
type DefaultValidation struct {
Capabilities Capabilities
TxValidatorV1_2 TransactionValidator
TxValidatorV1_3 TransactionValidator
TxValidatorV2_0 TransactionValidator
}
//go:generate mockery -dir . -name TransactionValidator -case underscore -output mocks/
type TransactionValidator interface {
Validate(block *common.Block, namespace string, txPosition int, actionPosition int, policy []byte) commonerrors.TxValidationError
}
func (v *DefaultValidation) Validate(block *common.Block, namespace string, txPosition int, actionPosition int, contextData ...validation.ContextDatum) error {
if len(contextData) == 0 {
logger.Panicf("Expected to receive policy bytes in context data")
}
serializedPolicy, isSerializedPolicy := contextData[0].(SerializedPolicy)
if !isSerializedPolicy {
logger.Panicf("Expected to receive a serialized policy in the first context data")
}
if block == nil || block.Data == nil {
return errors.New("empty block")
}
if txPosition >= len(block.Data.Data) {
return errors.Errorf("block has only %d transactions, but requested tx at position %d", len(block.Data.Data), txPosition)
}
if block.Header == nil {
return errors.Errorf("no block header")
}
var err error
switch {
case v.Capabilities.V2_0Validation():
err = v.TxValidatorV2_0.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())
case v.Capabilities.V1_3Validation():
err = v.TxValidatorV1_3.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())
case v.Capabilities.V1_2Validation():
fallthrough
default:
err = v.TxValidatorV1_2.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())
}
logger.Debugf("block %d, namespace: %s, tx %d validation results is: %v", block.Header.Number, namespace, txPosition, err)
return convertErrorTypeOrPanic(err)
}
func convertErrorTypeOrPanic(err error) error {
if err == nil {
return nil
}
if err, isExecutionError := err.(*commonerrors.VSCCExecutionFailureError); isExecutionError {
return &validation.ExecutionFailureError{
Reason: err.Error(),
}
}
if err, isEndorsementError := err.(*commonerrors.VSCCEndorsementPolicyError); isEndorsementError {
return err
}
logger.Panicf("Programming error: The error is %v, of type %v but expected to be either ExecutionFailureError or VSCCEndorsementPolicyError", err, reflect.TypeOf(err))
return &validation.ExecutionFailureError{Reason: fmt.Sprintf("error of type %v returned from VSCC", reflect.TypeOf(err))}
}
func (v *DefaultValidation) Init(dependencies ...validation.Dependency) error {
var (
d IdentityDeserializer
c Capabilities
sf StateFetcher
pe PolicyEvaluator
cor plugindispatcher.CollectionResources
)
for _, dep := range dependencies {
if deserializer, isIdentityDeserializer := dep.(IdentityDeserializer); isIdentityDeserializer {
d = deserializer
}
if capabilities, isCapabilities := dep.(Capabilities); isCapabilities {
c = capabilities
}
if stateFetcher, isStateFetcher := dep.(StateFetcher); isStateFetcher {
sf = stateFetcher
}
if policyEvaluator, isPolicyFetcher := dep.(PolicyEvaluator); isPolicyFetcher {
pe = policyEvaluator
}
if collectionResources, isCollectionResources := dep.(plugindispatcher.CollectionResources); isCollectionResources {
cor = collectionResources
}
}
if sf == nil {
return errors.New("stateFetcher not passed in init")
}
if d == nil {
return errors.New("identityDeserializer not passed in init")
}
if c == nil {
return errors.New("capabilities not passed in init")
}
if pe == nil {
return errors.New("policy fetcher not passed in init")
}
if cor == nil {
return errors.New("collection resources not passed in init")
}
v.Capabilities = c
v.TxValidatorV1_2 = v12.New(c, sf, d, pe)
v.TxValidatorV1_3 = v13.New(c, sf, d, pe)
v.TxValidatorV2_0 = v20.New(c, sf, d, pe, cor)
return nil
}