You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.2 KiB
184 lines
5.2 KiB
// Copyright (c) 2014-2015 The btcsuite developers |
|
// Use of this source code is governed by an ISC |
|
// license that can be found in the LICENSE file. |
|
|
|
package wire |
|
|
|
import ( |
|
"fmt" |
|
"io" |
|
) |
|
|
|
// RejectCode represents a numeric value by which a remote peer indicates |
|
// why a message was rejected. |
|
type RejectCode uint8 |
|
|
|
// These constants define the various supported reject codes. |
|
const ( |
|
RejectMalformed RejectCode = 0x01 |
|
RejectInvalid RejectCode = 0x10 |
|
RejectObsolete RejectCode = 0x11 |
|
RejectDuplicate RejectCode = 0x12 |
|
RejectNonstandard RejectCode = 0x40 |
|
RejectDust RejectCode = 0x41 |
|
RejectInsufficientFee RejectCode = 0x42 |
|
RejectCheckpoint RejectCode = 0x43 |
|
) |
|
|
|
// Map of reject codes back strings for pretty printing. |
|
var rejectCodeStrings = map[RejectCode]string{ |
|
RejectMalformed: "REJECT_MALFORMED", |
|
RejectInvalid: "REJECT_INVALID", |
|
RejectObsolete: "REJECT_OBSOLETE", |
|
RejectDuplicate: "REJECT_DUPLICATE", |
|
RejectNonstandard: "REJECT_NONSTANDARD", |
|
RejectDust: "REJECT_DUST", |
|
RejectInsufficientFee: "REJECT_INSUFFICIENTFEE", |
|
RejectCheckpoint: "REJECT_CHECKPOINT", |
|
} |
|
|
|
// String returns the RejectCode in human-readable form. |
|
func (code RejectCode) String() string { |
|
if s, ok := rejectCodeStrings[code]; ok { |
|
return s |
|
} |
|
|
|
return fmt.Sprintf("Unknown RejectCode (%d)", uint8(code)) |
|
} |
|
|
|
// MsgReject implements the Message interface and represents a bitcoin reject |
|
// message. |
|
// |
|
// This message was not added until protocol version RejectVersion. |
|
type MsgReject struct { |
|
// Cmd is the command for the message which was rejected such as |
|
// as CmdBlock or CmdTx. This can be obtained from the Command function |
|
// of a Message. |
|
Cmd string |
|
|
|
// RejectCode is a code indicating why the command was rejected. It |
|
// is encoded as a uint8 on the wire. |
|
Code RejectCode |
|
|
|
// Reason is a human-readable string with specific details (over and |
|
// above the reject code) about why the command was rejected. |
|
Reason string |
|
|
|
// Hash identifies a specific block or transaction that was rejected |
|
// and therefore only applies the MsgBlock and MsgTx messages. |
|
Hash ShaHash |
|
} |
|
|
|
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. |
|
// This is part of the Message interface implementation. |
|
func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32) error { |
|
if pver < RejectVersion { |
|
str := fmt.Sprintf("reject message invalid for protocol "+ |
|
"version %d", pver) |
|
return messageError("MsgReject.BtcDecode", str) |
|
} |
|
|
|
// Command that was rejected. |
|
cmd, err := readVarString(r, pver) |
|
if err != nil { |
|
return err |
|
} |
|
msg.Cmd = cmd |
|
|
|
// Code indicating why the command was rejected. |
|
err = readElement(r, &msg.Code) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Human readable string with specific details (over and above the |
|
// reject code above) about why the command was rejected. |
|
reason, err := readVarString(r, pver) |
|
if err != nil { |
|
return err |
|
} |
|
msg.Reason = reason |
|
|
|
// CmdBlock and CmdTx messages have an additional hash field that |
|
// identifies the specific block or transaction. |
|
if msg.Cmd == CmdBlock || msg.Cmd == CmdTx { |
|
err := readElement(r, &msg.Hash) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. |
|
// This is part of the Message interface implementation. |
|
func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32) error { |
|
if pver < RejectVersion { |
|
str := fmt.Sprintf("reject message invalid for protocol "+ |
|
"version %d", pver) |
|
return messageError("MsgReject.BtcEncode", str) |
|
} |
|
|
|
// Command that was rejected. |
|
err := writeVarString(w, pver, msg.Cmd) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Code indicating why the command was rejected. |
|
err = writeElement(w, msg.Code) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Human readable string with specific details (over and above the |
|
// reject code above) about why the command was rejected. |
|
err = writeVarString(w, pver, msg.Reason) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// CmdBlock and CmdTx messages have an additional hash field that |
|
// identifies the specific block or transaction. |
|
if msg.Cmd == CmdBlock || msg.Cmd == CmdTx { |
|
err := writeElement(w, &msg.Hash) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// Command returns the protocol command string for the message. This is part |
|
// of the Message interface implementation. |
|
func (msg *MsgReject) Command() string { |
|
return CmdReject |
|
} |
|
|
|
// MaxPayloadLength returns the maximum length the payload can be for the |
|
// receiver. This is part of the Message interface implementation. |
|
func (msg *MsgReject) MaxPayloadLength(pver uint32) uint32 { |
|
plen := uint32(0) |
|
// The reject message did not exist before protocol version |
|
// RejectVersion. |
|
if pver >= RejectVersion { |
|
// Unfortunately the bitcoin protocol does not enforce a sane |
|
// limit on the length of the reason, so the max payload is the |
|
// overall maximum message payload. |
|
plen = MaxMessagePayload |
|
} |
|
|
|
return plen |
|
} |
|
|
|
// NewMsgReject returns a new bitcoin reject message that conforms to the |
|
// Message interface. See MsgReject for details. |
|
func NewMsgReject(command string, code RejectCode, reason string) *MsgReject { |
|
return &MsgReject{ |
|
Cmd: command, |
|
Code: code, |
|
Reason: reason, |
|
} |
|
}
|
|
|