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.
160 lines
6.7 KiB
160 lines
6.7 KiB
9 years ago
|
// Copyright (c) 2013-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 implements the bitcoin wire protocol.
|
||
|
|
||
|
For the complete details of the bitcoin protocol, see the official wiki entry
|
||
|
at https://en.bitcoin.it/wiki/Protocol_specification. The following only serves
|
||
|
as a quick overview to provide information on how to use the package.
|
||
|
|
||
|
At a high level, this package provides support for marshalling and unmarshalling
|
||
|
supported bitcoin messages to and from the wire. This package does not deal
|
||
|
with the specifics of message handling such as what to do when a message is
|
||
|
received. This provides the caller with a high level of flexibility.
|
||
|
|
||
|
Bitcoin Message Overview
|
||
|
|
||
|
The bitcoin protocol consists of exchanging messages between peers. Each
|
||
|
message is preceded by a header which identifies information about it such as
|
||
|
which bitcoin network it is a part of, its type, how big it is, and a checksum
|
||
|
to verify validity. All encoding and decoding of message headers is handled by
|
||
|
this package.
|
||
|
|
||
|
To accomplish this, there is a generic interface for bitcoin messages named
|
||
|
Message which allows messages of any type to be read, written, or passed around
|
||
|
through channels, functions, etc. In addition, concrete implementations of most
|
||
|
of the currently supported bitcoin messages are provided. For these supported
|
||
|
messages, all of the details of marshalling and unmarshalling to and from the
|
||
|
wire using bitcoin encoding are handled so the caller doesn't have to concern
|
||
|
themselves with the specifics.
|
||
|
|
||
|
Message Interaction
|
||
|
|
||
|
The following provides a quick summary of how the bitcoin messages are intended
|
||
|
to interact with one another. As stated above, these interactions are not
|
||
|
directly handled by this package. For more in-depth details about the
|
||
|
appropriate interactions, see the official bitcoin protocol wiki entry at
|
||
|
https://en.bitcoin.it/wiki/Protocol_specification.
|
||
|
|
||
|
The initial handshake consists of two peers sending each other a version message
|
||
|
(MsgVersion) followed by responding with a verack message (MsgVerAck). Both
|
||
|
peers use the information in the version message (MsgVersion) to negotiate
|
||
|
things such as protocol version and supported services with each other. Once
|
||
|
the initial handshake is complete, the following chart indicates message
|
||
|
interactions in no particular order.
|
||
|
|
||
|
Peer A Sends Peer B Responds
|
||
|
----------------------------------------------------------------------------
|
||
|
getaddr message (MsgGetAddr) addr message (MsgAddr)
|
||
|
getblocks message (MsgGetBlocks) inv message (MsgInv)
|
||
|
inv message (MsgInv) getdata message (MsgGetData)
|
||
|
getdata message (MsgGetData) block message (MsgBlock) -or-
|
||
|
tx message (MsgTx) -or-
|
||
|
notfound message (MsgNotFound)
|
||
|
getheaders message (MsgGetHeaders) headers message (MsgHeaders)
|
||
|
ping message (MsgPing) pong message (MsgHeaders)* -or-
|
||
|
(none -- Ability to send message is enough)
|
||
|
|
||
|
NOTES:
|
||
|
* The pong message was not added until later protocol versions as defined
|
||
|
in BIP0031. The BIP0031Version constant can be used to detect a recent
|
||
|
enough protocol version for this purpose (version > BIP0031Version).
|
||
|
|
||
|
Common Parameters
|
||
|
|
||
|
There are several common parameters that arise when using this package to read
|
||
|
and write bitcoin messages. The following sections provide a quick overview of
|
||
|
these parameters so the next sections can build on them.
|
||
|
|
||
|
Protocol Version
|
||
|
|
||
|
The protocol version should be negotiated with the remote peer at a higher
|
||
|
level than this package via the version (MsgVersion) message exchange, however,
|
||
|
this package provides the wire.ProtocolVersion constant which indicates the
|
||
|
latest protocol version this package supports and is typically the value to use
|
||
|
for all outbound connections before a potentially lower protocol version is
|
||
|
negotiated.
|
||
|
|
||
|
Bitcoin Network
|
||
|
|
||
|
The bitcoin network is a magic number which is used to identify the start of a
|
||
|
message and which bitcoin network the message applies to. This package provides
|
||
|
the following constants:
|
||
|
|
||
|
wire.MainNet
|
||
|
wire.TestNet (Regression test network)
|
||
|
wire.TestNet3 (Test network version 3)
|
||
|
wire.SimNet (Simulation test network)
|
||
|
|
||
|
Determining Message Type
|
||
|
|
||
|
As discussed in the bitcoin message overview section, this package reads
|
||
|
and writes bitcoin messages using a generic interface named Message. In
|
||
|
order to determine the actual concrete type of the message, use a type
|
||
|
switch or type assertion. An example of a type switch follows:
|
||
|
|
||
|
// Assumes msg is already a valid concrete message such as one created
|
||
|
// via NewMsgVersion or read via ReadMessage.
|
||
|
switch msg := msg.(type) {
|
||
|
case *wire.MsgVersion:
|
||
|
// The message is a pointer to a MsgVersion struct.
|
||
|
fmt.Printf("Protocol version: %v", msg.ProtocolVersion)
|
||
|
case *wire.MsgBlock:
|
||
|
// The message is a pointer to a MsgBlock struct.
|
||
|
fmt.Printf("Number of tx in block: %v", msg.Header.TxnCount)
|
||
|
}
|
||
|
|
||
|
Reading Messages
|
||
|
|
||
|
In order to unmarshall bitcoin messages from the wire, use the ReadMessage
|
||
|
function. It accepts any io.Reader, but typically this will be a net.Conn to
|
||
|
a remote node running a bitcoin peer. Example syntax is:
|
||
|
|
||
|
// Reads and validates the next bitcoin message from conn using the
|
||
|
// protocol version pver and the bitcoin network btcnet. The returns
|
||
|
// are a wire.Message, a []byte which contains the unmarshalled
|
||
|
// raw payload, and a possible error.
|
||
|
msg, rawPayload, err := wire.ReadMessage(conn, pver, btcnet)
|
||
|
if err != nil {
|
||
|
// Log and handle the error
|
||
|
}
|
||
|
|
||
|
Writing Messages
|
||
|
|
||
|
In order to marshall bitcoin messages to the wire, use the WriteMessage
|
||
|
function. It accepts any io.Writer, but typically this will be a net.Conn to
|
||
|
a remote node running a bitcoin peer. Example syntax to request addresses
|
||
|
from a remote peer is:
|
||
|
|
||
|
// Create a new getaddr bitcoin message.
|
||
|
msg := wire.NewMsgGetAddr()
|
||
|
|
||
|
// Writes a bitcoin message msg to conn using the protocol version
|
||
|
// pver, and the bitcoin network btcnet. The return is a possible
|
||
|
// error.
|
||
|
err := wire.WriteMessage(conn, msg, pver, btcnet)
|
||
|
if err != nil {
|
||
|
// Log and handle the error
|
||
|
}
|
||
|
|
||
|
Errors
|
||
|
|
||
|
Errors returned by this package are either the raw errors provided by underlying
|
||
|
calls to read/write from streams such as io.EOF, io.ErrUnexpectedEOF, and
|
||
|
io.ErrShortWrite, or of type wire.MessageError. This allows the caller to
|
||
|
differentiate between general IO errors and malformed messages through type
|
||
|
assertions.
|
||
|
|
||
|
Bitcoin Improvement Proposals
|
||
|
|
||
|
This package includes spec changes outlined by the following BIPs:
|
||
|
|
||
|
BIP0014 (https://en.bitcoin.it/wiki/BIP_0014)
|
||
|
BIP0031 (https://en.bitcoin.it/wiki/BIP_0031)
|
||
|
BIP0035 (https://en.bitcoin.it/wiki/BIP_0035)
|
||
|
BIP0037 (https://en.bitcoin.it/wiki/BIP_0037)
|
||
|
*/
|
||
|
package wire
|