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