OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / wire / msgreject.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 wire
6
7 import (
8         "fmt"
9         "io"
10
11         "github.com/btcsuite/btcd/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 }