OSDN Git Service

b0d42be4209754ab8ad0e0207f1bf134d1762a09
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / mempool / error.go
1 // Copyright (c) 2014-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package mempool
6
7 import (
8         "github.com/btcsuite/btcd/blockchain"
9         "github.com/btcsuite/btcd/wire"
10 )
11
12 // RuleError identifies a rule violation.  It is used to indicate that
13 // processing of a transaction failed due to one of the many validation
14 // rules.  The caller can use type assertions to determine if a failure was
15 // specifically due to a rule violation and use the Err field to access the
16 // underlying error, which will be either a TxRuleError or a
17 // blockchain.RuleError.
18 type RuleError struct {
19         Err error
20 }
21
22 // Error satisfies the error interface and prints human-readable errors.
23 func (e RuleError) Error() string {
24         if e.Err == nil {
25                 return "<nil>"
26         }
27         return e.Err.Error()
28 }
29
30 // TxRuleError identifies a rule violation.  It is used to indicate that
31 // processing of a transaction failed due to one of the many validation
32 // rules.  The caller can use type assertions to determine if a failure was
33 // specifically due to a rule violation and access the ErrorCode field to
34 // ascertain the specific reason for the rule violation.
35 type TxRuleError struct {
36         RejectCode  wire.RejectCode // The code to send with reject messages
37         Description string          // Human readable description of the issue
38 }
39
40 // Error satisfies the error interface and prints human-readable errors.
41 func (e TxRuleError) Error() string {
42         return e.Description
43 }
44
45 // txRuleError creates an underlying TxRuleError with the given a set of
46 // arguments and returns a RuleError that encapsulates it.
47 func txRuleError(c wire.RejectCode, desc string) RuleError {
48         return RuleError{
49                 Err: TxRuleError{RejectCode: c, Description: desc},
50         }
51 }
52
53 // chainRuleError returns a RuleError that encapsulates the given
54 // blockchain.RuleError.
55 func chainRuleError(chainErr blockchain.RuleError) RuleError {
56         return RuleError{
57                 Err: chainErr,
58         }
59 }
60
61 // extractRejectCode attempts to return a relevant reject code for a given error
62 // by examining the error for known types.  It will return true if a code
63 // was successfully extracted.
64 func extractRejectCode(err error) (wire.RejectCode, bool) {
65         // Pull the underlying error out of a RuleError.
66         if rerr, ok := err.(RuleError); ok {
67                 err = rerr.Err
68         }
69
70         switch err := err.(type) {
71         case blockchain.RuleError:
72                 // Convert the chain error to a reject code.
73                 var code wire.RejectCode
74                 switch err.ErrorCode {
75                 // Rejected due to duplicate.
76                 case blockchain.ErrDuplicateBlock:
77                         code = wire.RejectDuplicate
78
79                 // Rejected due to obsolete version.
80                 case blockchain.ErrBlockVersionTooOld:
81                         code = wire.RejectObsolete
82
83                 // Rejected due to checkpoint.
84                 case blockchain.ErrCheckpointTimeTooOld:
85                         fallthrough
86                 case blockchain.ErrDifficultyTooLow:
87                         fallthrough
88                 case blockchain.ErrBadCheckpoint:
89                         fallthrough
90                 case blockchain.ErrForkTooOld:
91                         code = wire.RejectCheckpoint
92
93                 // Everything else is due to the block or transaction being invalid.
94                 default:
95                         code = wire.RejectInvalid
96                 }
97
98                 return code, true
99
100         case TxRuleError:
101                 return err.RejectCode, true
102
103         case nil:
104                 return wire.RejectInvalid, false
105         }
106
107         return wire.RejectInvalid, false
108 }
109
110 // ErrToRejectErr examines the underlying type of the error and returns a reject
111 // code and string appropriate to be sent in a wire.MsgReject message.
112 func ErrToRejectErr(err error) (wire.RejectCode, string) {
113         // Return the reject code along with the error text if it can be
114         // extracted from the error.
115         rejectCode, found := extractRejectCode(err)
116         if found {
117                 return rejectCode, err.Error()
118         }
119
120         // Return a generic rejected string if there is no error.  This really
121         // should not happen unless the code elsewhere is not setting an error
122         // as it should be, but it's best to be safe and simply return a generic
123         // string rather than allowing the following code that dereferences the
124         // err to panic.
125         if err == nil {
126                 return wire.RejectInvalid, "rejected"
127         }
128
129         // When the underlying error is not one of the above cases, just return
130         // wire.RejectInvalid with a generic rejected string plus the error
131         // text.
132         return wire.RejectInvalid, "rejected: " + err.Error()
133 }