|
1 | 1 | /*
|
2 |
| - Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved. |
3 |
| - Copyright IBM Corp. 2017 All Rights Reserved. |
| 2 | +Copyright IBM Corp. All Rights Reserved. |
4 | 3 |
|
5 |
| - Licensed under the Apache License, Version 2.0 (the "License"); |
6 |
| - you may not use this file except in compliance with the License. |
7 |
| - You may obtain a copy of the License at |
8 |
| -
|
9 |
| - http://www.apache.org/licenses/LICENSE-2.0 |
10 |
| -
|
11 |
| - Unless required by applicable law or agreed to in writing, software |
12 |
| - distributed under the License is distributed on an "AS IS" BASIS, |
13 |
| - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 |
| - See the License for the specific language governing permissions and |
15 |
| - limitations under the License. |
| 4 | +SPDX-License-Identifier: Apache-2.0 |
16 | 5 | */
|
17 | 6 |
|
18 | 7 | package errors
|
19 | 8 |
|
20 |
| -import ( |
21 |
| - "bytes" |
22 |
| - "fmt" |
23 |
| - "regexp" |
24 |
| - "runtime" |
25 |
| -) |
26 |
| - |
27 |
| -// MaxCallStackLength is the maximum length of the stored call stack |
28 |
| -const MaxCallStackLength = 30 |
29 |
| - |
30 |
| -var ( |
31 |
| - componentPattern = "[A-Za-z]{3}" |
32 |
| - reasonPattern = "[0-9]{3}" |
33 |
| -) |
34 |
| - |
35 |
| -// CallStackError is a general interface for Fabric errors |
36 |
| -type CallStackError interface { |
37 |
| - error |
38 |
| - GetStack() string |
39 |
| - GetErrorCode() string |
40 |
| - GetComponentCode() string |
41 |
| - GetReasonCode() string |
42 |
| - Message() string |
43 |
| - GenerateStack(bool) CallStackError |
44 |
| - WrapError(error) CallStackError |
45 |
| -} |
46 |
| - |
47 |
| -type callstack []uintptr |
48 |
| - |
49 |
| -// callError is the 'super class' of all errors |
50 |
| -type callError struct { |
51 |
| - stack callstack |
52 |
| - componentcode string |
53 |
| - reasoncode string |
54 |
| - message string |
55 |
| - args []interface{} |
56 |
| - stackGetter func(callstack) string |
57 |
| - prevErr error |
58 |
| -} |
59 |
| - |
60 |
| -func setupCallError(e *callError, generateStack bool) { |
61 |
| - if !generateStack { |
62 |
| - e.stackGetter = noopGetStack |
63 |
| - return |
64 |
| - } |
65 |
| - e.stackGetter = getStack |
66 |
| - stack := make([]uintptr, MaxCallStackLength) |
67 |
| - skipCallersAndSetup := 2 |
68 |
| - length := runtime.Callers(skipCallersAndSetup, stack[:]) |
69 |
| - e.stack = stack[:length] |
70 |
| -} |
71 |
| - |
72 |
| -// Error comes from the error interface - it returns the error message and |
73 |
| -// appends the callstack, if available |
74 |
| -func (e *callError) Error() string { |
75 |
| - message := e.GetErrorCode() + " - " + fmt.Sprintf(e.message, e.args...) |
76 |
| - // check that the error has a callstack before proceeding |
77 |
| - if e.GetStack() != "" { |
78 |
| - message = appendCallStack(message, e.GetStack()) |
79 |
| - } |
80 |
| - if e.prevErr != nil { |
81 |
| - message += "\nCaused by: " + e.prevErr.Error() |
82 |
| - } |
83 |
| - return message |
84 |
| -} |
85 |
| - |
86 |
| -// GetStack returns the call stack as a string |
87 |
| -func (e *callError) GetStack() string { |
88 |
| - return e.stackGetter(e.stack) |
89 |
| -} |
90 |
| - |
91 |
| -// GetComponentCode returns the component name |
92 |
| -func (e *callError) GetComponentCode() string { |
93 |
| - return e.componentcode |
94 |
| -} |
95 |
| - |
96 |
| -// GetReasonCode returns the reason code - i.e. why the error occurred |
97 |
| -func (e *callError) GetReasonCode() string { |
98 |
| - return e.reasoncode |
99 |
| -} |
100 |
| - |
101 |
| -// GetErrorCode returns a formatted error code string |
102 |
| -func (e *callError) GetErrorCode() string { |
103 |
| - return fmt.Sprintf("%s:%s", e.componentcode, e.reasoncode) |
104 |
| -} |
105 |
| - |
106 |
| -// Message returns the corresponding error message for this error in default |
107 |
| -// language. |
108 |
| -func (e *callError) Message() string { |
109 |
| - message := e.GetErrorCode() + " - " + fmt.Sprintf(e.message, e.args...) |
110 |
| - |
111 |
| - if e.prevErr != nil { |
112 |
| - switch previousError := e.prevErr.(type) { |
113 |
| - case CallStackError: |
114 |
| - message += "\nCaused by: " + previousError.Message() |
115 |
| - default: |
116 |
| - message += "\nCaused by: " + e.prevErr.Error() |
117 |
| - } |
118 |
| - } |
119 |
| - return message |
120 |
| -} |
121 |
| - |
122 |
| -func appendCallStack(message string, callstack string) string { |
123 |
| - return message + "\n" + callstack |
124 |
| -} |
125 |
| - |
126 |
| -// Error creates a CallStackError using a specific component code and reason |
127 |
| -// code (no callstack is generated) |
128 |
| -func Error(componentcode string, reasoncode string, message string, args ...interface{}) CallStackError { |
129 |
| - return newError(componentcode, reasoncode, message, args...).GenerateStack(false) |
130 |
| -} |
131 |
| - |
132 |
| -// ErrorWithCallstack creates a CallStackError using a specific component code |
133 |
| -// and reason code and generates its callstack |
134 |
| -func ErrorWithCallstack(componentcode string, reasoncode string, message string, args ...interface{}) CallStackError { |
135 |
| - return newError(componentcode, reasoncode, message, args...).GenerateStack(true) |
136 |
| -} |
137 |
| - |
138 |
| -func newError(componentcode string, reasoncode string, message string, args ...interface{}) CallStackError { |
139 |
| - e := &callError{} |
140 |
| - e.setErrorFields(componentcode, reasoncode, message, args...) |
141 |
| - return e |
142 |
| -} |
143 |
| - |
144 |
| -// GenerateStack generates the callstack for a CallStackError |
145 |
| -func (e *callError) GenerateStack(flag bool) CallStackError { |
146 |
| - setupCallError(e, flag) |
147 |
| - return e |
| 9 | +// VSCCInfoLookupFailureError error to indicate inability |
| 10 | +// to obtain VSCC information from LCCC |
| 11 | +type VSCCInfoLookupFailureError struct { |
| 12 | + Reason string |
148 | 13 | }
|
149 | 14 |
|
150 |
| -// WrapError wraps a previous error into a CallStackError |
151 |
| -func (e *callError) WrapError(prevErr error) CallStackError { |
152 |
| - e.prevErr = prevErr |
153 |
| - return e |
| 15 | +// Error returns reasons which lead to the failure |
| 16 | +func (e VSCCInfoLookupFailureError) Error() string { |
| 17 | + return e.Reason |
154 | 18 | }
|
155 | 19 |
|
156 |
| -func (e *callError) setErrorFields(componentcode string, reasoncode string, message string, args ...interface{}) { |
157 |
| - if isValidComponentOrReasonCode(componentcode, componentPattern) { |
158 |
| - e.componentcode = componentcode |
159 |
| - } |
160 |
| - if isValidComponentOrReasonCode(reasoncode, reasonPattern) { |
161 |
| - e.reasoncode = reasoncode |
162 |
| - } |
163 |
| - if message != "" { |
164 |
| - e.message = message |
165 |
| - } |
166 |
| - e.args = args |
| 20 | +// VSCCEndorsementPolicyError error to mark transaction |
| 21 | +// failed endrosement policy check |
| 22 | +type VSCCEndorsementPolicyError struct { |
| 23 | + Reason string |
167 | 24 | }
|
168 | 25 |
|
169 |
| -func isValidComponentOrReasonCode(componentOrReasonCode string, regExp string) bool { |
170 |
| - if componentOrReasonCode == "" { |
171 |
| - return false |
172 |
| - } |
173 |
| - re, _ := regexp.Compile(regExp) |
174 |
| - matched := re.FindString(componentOrReasonCode) |
175 |
| - if len(matched) != len(componentOrReasonCode) { |
176 |
| - return false |
177 |
| - } |
178 |
| - return true |
| 26 | +// Error returns reasons which lead to the failure |
| 27 | +func (e VSCCEndorsementPolicyError) Error() string { |
| 28 | + return e.Reason |
179 | 29 | }
|
180 | 30 |
|
181 |
| -func getStack(stack callstack) string { |
182 |
| - buf := bytes.Buffer{} |
183 |
| - if stack == nil { |
184 |
| - return fmt.Sprintf("No call stack available") |
185 |
| - } |
186 |
| - // this removes the core/errors module calls from the callstack because they |
187 |
| - // are not useful for debugging |
188 |
| - const firstNonErrorModuleCall int = 2 |
189 |
| - stack = stack[firstNonErrorModuleCall:] |
190 |
| - for i, pc := range stack { |
191 |
| - f := runtime.FuncForPC(pc) |
192 |
| - file, line := f.FileLine(pc) |
193 |
| - if i != len(stack)-1 { |
194 |
| - buf.WriteString(fmt.Sprintf("%s:%d %s\n", file, line, f.Name())) |
195 |
| - } else { |
196 |
| - buf.WriteString(fmt.Sprintf("%s:%d %s", file, line, f.Name())) |
197 |
| - } |
198 |
| - } |
199 |
| - return fmt.Sprintf("%s", buf.Bytes()) |
| 31 | +// VSCCExecutionFailureError error to indicate |
| 32 | +// failure during attempt of executing VSCC |
| 33 | +// endorsement policy check |
| 34 | +type VSCCExecutionFailureError struct { |
| 35 | + Reason string |
200 | 36 | }
|
201 | 37 |
|
202 |
| -func noopGetStack(stack callstack) string { |
203 |
| - return "" |
| 38 | +// Error returns reasons which lead to the failure |
| 39 | +func (e VSCCExecutionFailureError) Error() string { |
| 40 | + return e.Reason |
204 | 41 | }
|
0 commit comments