github.com/palcoin-project/palcd@v1.0.0/wire/msgreject.go (about)

     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 wire
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  
    11  	"github.com/palcoin-project/palcd/chaincfg/chainhash"
    12  )
    13  
    14  // RejectCode represents a numeric value by which a remote peer indicates
    15  // why a message was rejected.
    16  type RejectCode uint8
    17  
    18  // These constants define the various supported reject codes.
    19  const (
    20  	RejectMalformed       RejectCode = 0x01
    21  	RejectInvalid         RejectCode = 0x10
    22  	RejectObsolete        RejectCode = 0x11
    23  	RejectDuplicate       RejectCode = 0x12
    24  	RejectNonstandard     RejectCode = 0x40
    25  	RejectDust            RejectCode = 0x41
    26  	RejectInsufficientFee RejectCode = 0x42
    27  	RejectCheckpoint      RejectCode = 0x43
    28  )
    29  
    30  // Map of reject codes back strings for pretty printing.
    31  var rejectCodeStrings = map[RejectCode]string{
    32  	RejectMalformed:       "REJECT_MALFORMED",
    33  	RejectInvalid:         "REJECT_INVALID",
    34  	RejectObsolete:        "REJECT_OBSOLETE",
    35  	RejectDuplicate:       "REJECT_DUPLICATE",
    36  	RejectNonstandard:     "REJECT_NONSTANDARD",
    37  	RejectDust:            "REJECT_DUST",
    38  	RejectInsufficientFee: "REJECT_INSUFFICIENTFEE",
    39  	RejectCheckpoint:      "REJECT_CHECKPOINT",
    40  }
    41  
    42  // String returns the RejectCode in human-readable form.
    43  func (code RejectCode) String() string {
    44  	if s, ok := rejectCodeStrings[code]; ok {
    45  		return s
    46  	}
    47  
    48  	return fmt.Sprintf("Unknown RejectCode (%d)", uint8(code))
    49  }
    50  
    51  // MsgReject implements the Message interface and represents a bitcoin reject
    52  // message.
    53  //
    54  // This message was not added until protocol version RejectVersion.
    55  type MsgReject struct {
    56  	// Cmd is the command for the message which was rejected such as
    57  	// as CmdBlock or CmdTx.  This can be obtained from the Command function
    58  	// of a Message.
    59  	Cmd string
    60  
    61  	// RejectCode is a code indicating why the command was rejected.  It
    62  	// is encoded as a uint8 on the wire.
    63  	Code RejectCode
    64  
    65  	// Reason is a human-readable string with specific details (over and
    66  	// above the reject code) about why the command was rejected.
    67  	Reason string
    68  
    69  	// Hash identifies a specific block or transaction that was rejected
    70  	// and therefore only applies the MsgBlock and MsgTx messages.
    71  	Hash chainhash.Hash
    72  }
    73  
    74  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    75  // This is part of the Message interface implementation.
    76  func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error {
    77  	if pver < RejectVersion {
    78  		str := fmt.Sprintf("reject message invalid for protocol "+
    79  			"version %d", pver)
    80  		return messageError("MsgReject.BtcDecode", str)
    81  	}
    82  
    83  	// Command that was rejected.
    84  	cmd, err := ReadVarString(r, pver)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	msg.Cmd = cmd
    89  
    90  	// Code indicating why the command was rejected.
    91  	err = readElement(r, &msg.Code)
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	// Human readable string with specific details (over and above the
    97  	// reject code above) about why the command was rejected.
    98  	reason, err := ReadVarString(r, pver)
    99  	if err != nil {
   100  		return err
   101  	}
   102  	msg.Reason = reason
   103  
   104  	// CmdBlock and CmdTx messages have an additional hash field that
   105  	// identifies the specific block or transaction.
   106  	if msg.Cmd == CmdBlock || msg.Cmd == CmdTx {
   107  		err := readElement(r, &msg.Hash)
   108  		if err != nil {
   109  			return err
   110  		}
   111  	}
   112  
   113  	return nil
   114  }
   115  
   116  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
   117  // This is part of the Message interface implementation.
   118  func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
   119  	if pver < RejectVersion {
   120  		str := fmt.Sprintf("reject message invalid for protocol "+
   121  			"version %d", pver)
   122  		return messageError("MsgReject.BtcEncode", str)
   123  	}
   124  
   125  	// Command that was rejected.
   126  	err := WriteVarString(w, pver, msg.Cmd)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	// Code indicating why the command was rejected.
   132  	err = writeElement(w, msg.Code)
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	// Human readable string with specific details (over and above the
   138  	// reject code above) about why the command was rejected.
   139  	err = WriteVarString(w, pver, msg.Reason)
   140  	if err != nil {
   141  		return err
   142  	}
   143  
   144  	// CmdBlock and CmdTx messages have an additional hash field that
   145  	// identifies the specific block or transaction.
   146  	if msg.Cmd == CmdBlock || msg.Cmd == CmdTx {
   147  		err := writeElement(w, &msg.Hash)
   148  		if err != nil {
   149  			return err
   150  		}
   151  	}
   152  
   153  	return nil
   154  }
   155  
   156  // Command returns the protocol command string for the message.  This is part
   157  // of the Message interface implementation.
   158  func (msg *MsgReject) Command() string {
   159  	return CmdReject
   160  }
   161  
   162  // MaxPayloadLength returns the maximum length the payload can be for the
   163  // receiver.  This is part of the Message interface implementation.
   164  func (msg *MsgReject) MaxPayloadLength(pver uint32) uint32 {
   165  	plen := uint32(0)
   166  	// The reject message did not exist before protocol version
   167  	// RejectVersion.
   168  	if pver >= RejectVersion {
   169  		// Unfortunately the bitcoin protocol does not enforce a sane
   170  		// limit on the length of the reason, so the max payload is the
   171  		// overall maximum message payload.
   172  		plen = MaxMessagePayload
   173  	}
   174  
   175  	return plen
   176  }
   177  
   178  // NewMsgReject returns a new bitcoin reject message that conforms to the
   179  // Message interface.  See MsgReject for details.
   180  func NewMsgReject(command string, code RejectCode, reason string) *MsgReject {
   181  	return &MsgReject{
   182  		Cmd:    command,
   183  		Code:   code,
   184  		Reason: reason,
   185  	}
   186  }