OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / wire / message.go
diff --git a/vendor/github.com/btcsuite/btcd/wire/message.go b/vendor/github.com/btcsuite/btcd/wire/message.go
deleted file mode 100644 (file)
index 80e9fe3..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright (c) 2013-2016 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 (
-       "bytes"
-       "fmt"
-       "io"
-       "unicode/utf8"
-
-       "github.com/btcsuite/btcd/chaincfg/chainhash"
-)
-
-// MessageHeaderSize is the number of bytes in a bitcoin message header.
-// Bitcoin network (magic) 4 bytes + command 12 bytes + payload length 4 bytes +
-// checksum 4 bytes.
-const MessageHeaderSize = 24
-
-// CommandSize is the fixed size of all commands in the common bitcoin message
-// header.  Shorter commands must be zero padded.
-const CommandSize = 12
-
-// MaxMessagePayload is the maximum bytes a message can be regardless of other
-// individual limits imposed by messages themselves.
-const MaxMessagePayload = (1024 * 1024 * 32) // 32MB
-
-// Commands used in bitcoin message headers which describe the type of message.
-const (
-       CmdVersion     = "version"
-       CmdVerAck      = "verack"
-       CmdGetAddr     = "getaddr"
-       CmdAddr        = "addr"
-       CmdGetBlocks   = "getblocks"
-       CmdInv         = "inv"
-       CmdGetData     = "getdata"
-       CmdNotFound    = "notfound"
-       CmdBlock       = "block"
-       CmdTx          = "tx"
-       CmdGetHeaders  = "getheaders"
-       CmdHeaders     = "headers"
-       CmdPing        = "ping"
-       CmdPong        = "pong"
-       CmdAlert       = "alert"
-       CmdMemPool     = "mempool"
-       CmdFilterAdd   = "filteradd"
-       CmdFilterClear = "filterclear"
-       CmdFilterLoad  = "filterload"
-       CmdMerkleBlock = "merkleblock"
-       CmdReject      = "reject"
-       CmdSendHeaders = "sendheaders"
-       CmdFeeFilter   = "feefilter"
-)
-
-// MessageEncoding represents the wire message encoding format to be used.
-type MessageEncoding uint32
-
-const (
-       // BaseEncoding encodes all messages in the default format specified
-       // for the Bitcoin wire protocol.
-       BaseEncoding MessageEncoding = 1 << iota
-
-       // WitnessEncoding encodes all messages other than transaction messages
-       // using the default Bitcoin wire protocol specification. For transaction
-       // messages, the new encoding format detailed in BIP0144 will be used.
-       WitnessEncoding
-)
-
-// LatestEncoding is the most recently specified encoding for the Bitcoin wire
-// protocol.
-var LatestEncoding = WitnessEncoding
-
-// Message is an interface that describes a bitcoin message.  A type that
-// implements Message has complete control over the representation of its data
-// and may therefore contain additional or fewer fields than those which
-// are used directly in the protocol encoded message.
-type Message interface {
-       BtcDecode(io.Reader, uint32, MessageEncoding) error
-       BtcEncode(io.Writer, uint32, MessageEncoding) error
-       Command() string
-       MaxPayloadLength(uint32) uint32
-}
-
-// makeEmptyMessage creates a message of the appropriate concrete type based
-// on the command.
-func makeEmptyMessage(command string) (Message, error) {
-       var msg Message
-       switch command {
-       case CmdVersion:
-               msg = &MsgVersion{}
-
-       case CmdVerAck:
-               msg = &MsgVerAck{}
-
-       case CmdGetAddr:
-               msg = &MsgGetAddr{}
-
-       case CmdAddr:
-               msg = &MsgAddr{}
-
-       case CmdGetBlocks:
-               msg = &MsgGetBlocks{}
-
-       case CmdBlock:
-               msg = &MsgBlock{}
-
-       case CmdInv:
-               msg = &MsgInv{}
-
-       case CmdGetData:
-               msg = &MsgGetData{}
-
-       case CmdNotFound:
-               msg = &MsgNotFound{}
-
-       case CmdTx:
-               msg = &MsgTx{}
-
-       case CmdPing:
-               msg = &MsgPing{}
-
-       case CmdPong:
-               msg = &MsgPong{}
-
-       case CmdGetHeaders:
-               msg = &MsgGetHeaders{}
-
-       case CmdHeaders:
-               msg = &MsgHeaders{}
-
-       case CmdAlert:
-               msg = &MsgAlert{}
-
-       case CmdMemPool:
-               msg = &MsgMemPool{}
-
-       case CmdFilterAdd:
-               msg = &MsgFilterAdd{}
-
-       case CmdFilterClear:
-               msg = &MsgFilterClear{}
-
-       case CmdFilterLoad:
-               msg = &MsgFilterLoad{}
-
-       case CmdMerkleBlock:
-               msg = &MsgMerkleBlock{}
-
-       case CmdReject:
-               msg = &MsgReject{}
-
-       case CmdSendHeaders:
-               msg = &MsgSendHeaders{}
-
-       case CmdFeeFilter:
-               msg = &MsgFeeFilter{}
-
-       default:
-               return nil, fmt.Errorf("unhandled command [%s]", command)
-       }
-       return msg, nil
-}
-
-// messageHeader defines the header structure for all bitcoin protocol messages.
-type messageHeader struct {
-       magic    BitcoinNet // 4 bytes
-       command  string     // 12 bytes
-       length   uint32     // 4 bytes
-       checksum [4]byte    // 4 bytes
-}
-
-// readMessageHeader reads a bitcoin message header from r.
-func readMessageHeader(r io.Reader) (int, *messageHeader, error) {
-       // Since readElements doesn't return the amount of bytes read, attempt
-       // to read the entire header into a buffer first in case there is a
-       // short read so the proper amount of read bytes are known.  This works
-       // since the header is a fixed size.
-       var headerBytes [MessageHeaderSize]byte
-       n, err := io.ReadFull(r, headerBytes[:])
-       if err != nil {
-               return n, nil, err
-       }
-       hr := bytes.NewReader(headerBytes[:])
-
-       // Create and populate a messageHeader struct from the raw header bytes.
-       hdr := messageHeader{}
-       var command [CommandSize]byte
-       readElements(hr, &hdr.magic, &command, &hdr.length, &hdr.checksum)
-
-       // Strip trailing zeros from command string.
-       hdr.command = string(bytes.TrimRight(command[:], string(0)))
-
-       return n, &hdr, nil
-}
-
-// discardInput reads n bytes from reader r in chunks and discards the read
-// bytes.  This is used to skip payloads when various errors occur and helps
-// prevent rogue nodes from causing massive memory allocation through forging
-// header length.
-func discardInput(r io.Reader, n uint32) {
-       maxSize := uint32(10 * 1024) // 10k at a time
-       numReads := n / maxSize
-       bytesRemaining := n % maxSize
-       if n > 0 {
-               buf := make([]byte, maxSize)
-               for i := uint32(0); i < numReads; i++ {
-                       io.ReadFull(r, buf)
-               }
-       }
-       if bytesRemaining > 0 {
-               buf := make([]byte, bytesRemaining)
-               io.ReadFull(r, buf)
-       }
-}
-
-// WriteMessageN writes a bitcoin Message to w including the necessary header
-// information and returns the number of bytes written.    This function is the
-// same as WriteMessage except it also returns the number of bytes written.
-func WriteMessageN(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) (int, error) {
-       return WriteMessageWithEncodingN(w, msg, pver, btcnet, BaseEncoding)
-}
-
-// WriteMessage writes a bitcoin Message to w including the necessary header
-// information.  This function is the same as WriteMessageN except it doesn't
-// doesn't return the number of bytes written.  This function is mainly provided
-// for backwards compatibility with the original API, but it's also useful for
-// callers that don't care about byte counts.
-func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) error {
-       _, err := WriteMessageN(w, msg, pver, btcnet)
-       return err
-}
-
-// WriteMessageWithEncodingN writes a bitcoin Message to w including the
-// necessary header information and returns the number of bytes written.
-// This function is the same as WriteMessageN except it also allows the caller
-// to specify the message encoding format to be used when serializing wire
-// messages.
-func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32,
-       btcnet BitcoinNet, encoding MessageEncoding) (int, error) {
-
-       totalBytes := 0
-
-       // Enforce max command size.
-       var command [CommandSize]byte
-       cmd := msg.Command()
-       if len(cmd) > CommandSize {
-               str := fmt.Sprintf("command [%s] is too long [max %v]",
-                       cmd, CommandSize)
-               return totalBytes, messageError("WriteMessage", str)
-       }
-       copy(command[:], []byte(cmd))
-
-       // Encode the message payload.
-       var bw bytes.Buffer
-       err := msg.BtcEncode(&bw, pver, encoding)
-       if err != nil {
-               return totalBytes, err
-       }
-       payload := bw.Bytes()
-       lenp := len(payload)
-
-       // Enforce maximum overall message payload.
-       if lenp > MaxMessagePayload {
-               str := fmt.Sprintf("message payload is too large - encoded "+
-                       "%d bytes, but maximum message payload is %d bytes",
-                       lenp, MaxMessagePayload)
-               return totalBytes, messageError("WriteMessage", str)
-       }
-
-       // Enforce maximum message payload based on the message type.
-       mpl := msg.MaxPayloadLength(pver)
-       if uint32(lenp) > mpl {
-               str := fmt.Sprintf("message payload is too large - encoded "+
-                       "%d bytes, but maximum message payload size for "+
-                       "messages of type [%s] is %d.", lenp, cmd, mpl)
-               return totalBytes, messageError("WriteMessage", str)
-       }
-
-       // Create header for the message.
-       hdr := messageHeader{}
-       hdr.magic = btcnet
-       hdr.command = cmd
-       hdr.length = uint32(lenp)
-       copy(hdr.checksum[:], chainhash.DoubleHashB(payload)[0:4])
-
-       // Encode the header for the message.  This is done to a buffer
-       // rather than directly to the writer since writeElements doesn't
-       // return the number of bytes written.
-       hw := bytes.NewBuffer(make([]byte, 0, MessageHeaderSize))
-       writeElements(hw, hdr.magic, command, hdr.length, hdr.checksum)
-
-       // Write header.
-       n, err := w.Write(hw.Bytes())
-       totalBytes += n
-       if err != nil {
-               return totalBytes, err
-       }
-
-       // Write payload.
-       n, err = w.Write(payload)
-       totalBytes += n
-       return totalBytes, err
-}
-
-// ReadMessageWithEncodingN reads, validates, and parses the next bitcoin Message
-// from r for the provided protocol version and bitcoin network.  It returns the
-// number of bytes read in addition to the parsed Message and raw bytes which
-// comprise the message.  This function is the same as ReadMessageN except it
-// allows the caller to specify which message encoding is to to consult when
-// decoding wire messages.
-func ReadMessageWithEncodingN(r io.Reader, pver uint32, btcnet BitcoinNet,
-       enc MessageEncoding) (int, Message, []byte, error) {
-
-       totalBytes := 0
-       n, hdr, err := readMessageHeader(r)
-       totalBytes += n
-       if err != nil {
-               return totalBytes, nil, nil, err
-       }
-
-       // Enforce maximum message payload.
-       if hdr.length > MaxMessagePayload {
-               str := fmt.Sprintf("message payload is too large - header "+
-                       "indicates %d bytes, but max message payload is %d "+
-                       "bytes.", hdr.length, MaxMessagePayload)
-               return totalBytes, nil, nil, messageError("ReadMessage", str)
-
-       }
-
-       // Check for messages from the wrong bitcoin network.
-       if hdr.magic != btcnet {
-               discardInput(r, hdr.length)
-               str := fmt.Sprintf("message from other network [%v]", hdr.magic)
-               return totalBytes, nil, nil, messageError("ReadMessage", str)
-       }
-
-       // Check for malformed commands.
-       command := hdr.command
-       if !utf8.ValidString(command) {
-               discardInput(r, hdr.length)
-               str := fmt.Sprintf("invalid command %v", []byte(command))
-               return totalBytes, nil, nil, messageError("ReadMessage", str)
-       }
-
-       // Create struct of appropriate message type based on the command.
-       msg, err := makeEmptyMessage(command)
-       if err != nil {
-               discardInput(r, hdr.length)
-               return totalBytes, nil, nil, messageError("ReadMessage",
-                       err.Error())
-       }
-
-       // Check for maximum length based on the message type as a malicious client
-       // could otherwise create a well-formed header and set the length to max
-       // numbers in order to exhaust the machine's memory.
-       mpl := msg.MaxPayloadLength(pver)
-       if hdr.length > mpl {
-               discardInput(r, hdr.length)
-               str := fmt.Sprintf("payload exceeds max length - header "+
-                       "indicates %v bytes, but max payload size for "+
-                       "messages of type [%v] is %v.", hdr.length, command, mpl)
-               return totalBytes, nil, nil, messageError("ReadMessage", str)
-       }
-
-       // Read payload.
-       payload := make([]byte, hdr.length)
-       n, err = io.ReadFull(r, payload)
-       totalBytes += n
-       if err != nil {
-               return totalBytes, nil, nil, err
-       }
-
-       // Test checksum.
-       checksum := chainhash.DoubleHashB(payload)[0:4]
-       if !bytes.Equal(checksum[:], hdr.checksum[:]) {
-               str := fmt.Sprintf("payload checksum failed - header "+
-                       "indicates %v, but actual checksum is %v.",
-                       hdr.checksum, checksum)
-               return totalBytes, nil, nil, messageError("ReadMessage", str)
-       }
-
-       // Unmarshal message.  NOTE: This must be a *bytes.Buffer since the
-       // MsgVersion BtcDecode function requires it.
-       pr := bytes.NewBuffer(payload)
-       err = msg.BtcDecode(pr, pver, enc)
-       if err != nil {
-               return totalBytes, nil, nil, err
-       }
-
-       return totalBytes, msg, payload, nil
-}
-
-// ReadMessageN reads, validates, and parses the next bitcoin Message from r for
-// the provided protocol version and bitcoin network.  It returns the number of
-// bytes read in addition to the parsed Message and raw bytes which comprise the
-// message.  This function is the same as ReadMessage except it also returns the
-// number of bytes read.
-func ReadMessageN(r io.Reader, pver uint32, btcnet BitcoinNet) (int, Message, []byte, error) {
-       return ReadMessageWithEncodingN(r, pver, btcnet, BaseEncoding)
-}
-
-// ReadMessage reads, validates, and parses the next bitcoin Message from r for
-// the provided protocol version and bitcoin network.  It returns the parsed
-// Message and raw bytes which comprise the message.  This function only differs
-// from ReadMessageN in that it doesn't return the number of bytes read.  This
-// function is mainly provided for backwards compatibility with the original
-// API, but it's also useful for callers that don't care about byte counts.
-func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, error) {
-       _, msg, buf, err := ReadMessageN(r, pver, btcnet)
-       return msg, buf, err
-}