github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/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/BlockABC/godash/blockchain"
    10  	"github.com/BlockABC/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  }