forked from cerc-io/ipld-eth-server
Update dependencies
- uses newer version of go-ethereum required for go1.11
This commit is contained in:
+1
@@ -4,6 +4,7 @@ wire
|
||||
[](https://travis-ci.org/btcsuite/btcd)
|
||||
[](http://copyfree.org)
|
||||
[](http://godoc.org/github.com/btcsuite/btcd/wire)
|
||||
=======
|
||||
|
||||
Package wire implements the bitcoin wire protocol. A comprehensive suite of
|
||||
tests with 100% test coverage is provided to ensure proper functionality.
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ type BlockHeader struct {
|
||||
// Version of the block. This is not the same as the protocol version.
|
||||
Version int32
|
||||
|
||||
// Hash of the previous block in the block chain.
|
||||
// Hash of the previous block header in the block chain.
|
||||
PrevBlock chainhash.Hash
|
||||
|
||||
// Merkle tree reference to hash of all transactions for the block.
|
||||
|
||||
+2
-2
@@ -630,8 +630,8 @@ func WriteVarString(w io.Writer, pver uint32, str string) error {
|
||||
// ReadVarBytes reads a variable length byte array. A byte array is encoded
|
||||
// as a varInt containing the length of the array followed by the bytes
|
||||
// themselves. An error is returned if the length is greater than the
|
||||
// passed maxAllowed parameter which helps protect against memory exhuastion
|
||||
// attacks and forced panics thorugh malformed messages. The fieldName
|
||||
// passed maxAllowed parameter which helps protect against memory exhaustion
|
||||
// attacks and forced panics through malformed messages. The fieldName
|
||||
// parameter is only used for the error message so it provides more context in
|
||||
// the error.
|
||||
func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32,
|
||||
|
||||
+47
-23
@@ -28,29 +28,35 @@ 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"
|
||||
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"
|
||||
CmdGetCFilters = "getcfilters"
|
||||
CmdGetCFHeaders = "getcfheaders"
|
||||
CmdGetCFCheckpt = "getcfcheckpt"
|
||||
CmdCFilter = "cfilter"
|
||||
CmdCFHeaders = "cfheaders"
|
||||
CmdCFCheckpt = "cfcheckpt"
|
||||
)
|
||||
|
||||
// MessageEncoding represents the wire message encoding format to be used.
|
||||
@@ -156,6 +162,24 @@ func makeEmptyMessage(command string) (Message, error) {
|
||||
case CmdFeeFilter:
|
||||
msg = &MsgFeeFilter{}
|
||||
|
||||
case CmdGetCFilters:
|
||||
msg = &MsgGetCFilters{}
|
||||
|
||||
case CmdGetCFHeaders:
|
||||
msg = &MsgGetCFHeaders{}
|
||||
|
||||
case CmdGetCFCheckpt:
|
||||
msg = &MsgGetCFCheckpt{}
|
||||
|
||||
case CmdCFilter:
|
||||
msg = &MsgCFilter{}
|
||||
|
||||
case CmdCFHeaders:
|
||||
msg = &MsgCFHeaders{}
|
||||
|
||||
case CmdCFCheckpt:
|
||||
msg = &MsgCFCheckpt{}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled command [%s]", command)
|
||||
}
|
||||
|
||||
+13
@@ -69,6 +69,13 @@ func TestMessage(t *testing.T) {
|
||||
bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0)
|
||||
msgMerkleBlock := NewMsgMerkleBlock(bh)
|
||||
msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block")
|
||||
msgGetCFilters := NewMsgGetCFilters(GCSFilterRegular, 0, &chainhash.Hash{})
|
||||
msgGetCFHeaders := NewMsgGetCFHeaders(GCSFilterRegular, 0, &chainhash.Hash{})
|
||||
msgGetCFCheckpt := NewMsgGetCFCheckpt(GCSFilterRegular, &chainhash.Hash{})
|
||||
msgCFilter := NewMsgCFilter(GCSFilterRegular, &chainhash.Hash{},
|
||||
[]byte("payload"))
|
||||
msgCFHeaders := NewMsgCFHeaders()
|
||||
msgCFCheckpt := NewMsgCFCheckpt(GCSFilterRegular, &chainhash.Hash{}, 0)
|
||||
|
||||
tests := []struct {
|
||||
in Message // Value to encode
|
||||
@@ -98,6 +105,12 @@ func TestMessage(t *testing.T) {
|
||||
{msgFilterLoad, msgFilterLoad, pver, MainNet, 35},
|
||||
{msgMerkleBlock, msgMerkleBlock, pver, MainNet, 110},
|
||||
{msgReject, msgReject, pver, MainNet, 79},
|
||||
{msgGetCFilters, msgGetCFilters, pver, MainNet, 61},
|
||||
{msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 61},
|
||||
{msgGetCFCheckpt, msgGetCFCheckpt, pver, MainNet, 57},
|
||||
{msgCFilter, msgCFilter, pver, MainNet, 65},
|
||||
{msgCFHeaders, msgCFHeaders, pver, MainNet, 90},
|
||||
{msgCFCheckpt, msgCFCheckpt, pver, MainNet, 58},
|
||||
}
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2018 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
const (
|
||||
// CFCheckptInterval is the gap (in number of blocks) between each
|
||||
// filter header checkpoint.
|
||||
CFCheckptInterval = 1000
|
||||
|
||||
// maxCFHeadersLen is the max number of filter headers we will attempt
|
||||
// to decode.
|
||||
maxCFHeadersLen = 100000
|
||||
)
|
||||
|
||||
// ErrInsaneCFHeaderCount signals that we were asked to decode an
|
||||
// unreasonable number of cfilter headers.
|
||||
var ErrInsaneCFHeaderCount = errors.New(
|
||||
"refusing to decode unreasonable number of filter headers")
|
||||
|
||||
// MsgCFCheckpt implements the Message interface and represents a bitcoin
|
||||
// cfcheckpt message. It is used to deliver committed filter header information
|
||||
// in response to a getcfcheckpt message (MsgGetCFCheckpt). See MsgGetCFCheckpt
|
||||
// for details on requesting the headers.
|
||||
type MsgCFCheckpt struct {
|
||||
FilterType FilterType
|
||||
StopHash chainhash.Hash
|
||||
FilterHeaders []*chainhash.Hash
|
||||
}
|
||||
|
||||
// AddCFHeader adds a new committed filter header to the message.
|
||||
func (msg *MsgCFCheckpt) AddCFHeader(header *chainhash.Hash) error {
|
||||
if len(msg.FilterHeaders) == cap(msg.FilterHeaders) {
|
||||
str := fmt.Sprintf("FilterHeaders has insufficient capacity for "+
|
||||
"additional header: len = %d", len(msg.FilterHeaders))
|
||||
return messageError("MsgCFCheckpt.AddCFHeader", str)
|
||||
}
|
||||
|
||||
msg.FilterHeaders = append(msg.FilterHeaders, header)
|
||||
return nil
|
||||
}
|
||||
|
||||
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
|
||||
// Read filter type
|
||||
err := readElement(r, &msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read stop hash
|
||||
err = readElement(r, &msg.StopHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read number of filter headers
|
||||
count, err := ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Refuse to decode an insane number of cfheaders.
|
||||
if count > maxCFHeadersLen {
|
||||
return ErrInsaneCFHeaderCount
|
||||
}
|
||||
|
||||
// Create a contiguous slice of hashes to deserialize into in order to
|
||||
// reduce the number of allocations.
|
||||
msg.FilterHeaders = make([]*chainhash.Hash, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
var cfh chainhash.Hash
|
||||
err := readElement(r, &cfh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg.FilterHeaders[i] = &cfh
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error {
|
||||
// Write filter type
|
||||
err := writeElement(w, msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write stop hash
|
||||
err = writeElement(w, msg.StopHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write length of FilterHeaders slice
|
||||
count := len(msg.FilterHeaders)
|
||||
err = WriteVarInt(w, pver, uint64(count))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, cfh := range msg.FilterHeaders {
|
||||
err := writeElement(w, cfh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deserialize decodes a filter header from r into the receiver using a format
|
||||
// that is suitable for long-term storage such as a database. This function
|
||||
// differs from BtcDecode in that BtcDecode decodes from the bitcoin wire
|
||||
// protocol as it was sent across the network. The wire encoding can
|
||||
// technically differ depending on the protocol version and doesn't even really
|
||||
// need to match the format of a stored filter header at all. As of the time
|
||||
// this comment was written, the encoded filter header is the same in both
|
||||
// instances, but there is a distinct difference and separating the two allows
|
||||
// the API to be flexible enough to deal with changes.
|
||||
func (msg *MsgCFCheckpt) Deserialize(r io.Reader) error {
|
||||
// At the current time, there is no difference between the wire encoding
|
||||
// and the stable long-term storage format. As a result, make use of
|
||||
// BtcDecode.
|
||||
return msg.BtcDecode(r, 0, BaseEncoding)
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgCFCheckpt) Command() string {
|
||||
return CmdCFCheckpt
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgCFCheckpt) MaxPayloadLength(pver uint32) uint32 {
|
||||
// Message size depends on the blockchain height, so return general limit
|
||||
// for all messages.
|
||||
return MaxMessagePayload
|
||||
}
|
||||
|
||||
// NewMsgCFCheckpt returns a new bitcoin cfheaders message that conforms to
|
||||
// the Message interface. See MsgCFCheckpt for details.
|
||||
func NewMsgCFCheckpt(filterType FilterType, stopHash *chainhash.Hash,
|
||||
headersCount int) *MsgCFCheckpt {
|
||||
return &MsgCFCheckpt{
|
||||
FilterType: filterType,
|
||||
StopHash: *stopHash,
|
||||
FilterHeaders: make([]*chainhash.Hash, 0, headersCount),
|
||||
}
|
||||
}
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
// Copyright (c) 2017 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"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxCFHeaderPayload is the maximum byte size of a committed
|
||||
// filter header.
|
||||
MaxCFHeaderPayload = chainhash.HashSize
|
||||
|
||||
// MaxCFHeadersPerMsg is the maximum number of committed filter headers
|
||||
// that can be in a single bitcoin cfheaders message.
|
||||
MaxCFHeadersPerMsg = 2000
|
||||
)
|
||||
|
||||
// MsgCFHeaders implements the Message interface and represents a bitcoin
|
||||
// cfheaders message. It is used to deliver committed filter header information
|
||||
// in response to a getcfheaders message (MsgGetCFHeaders). The maximum number
|
||||
// of committed filter headers per message is currently 2000. See
|
||||
// MsgGetCFHeaders for details on requesting the headers.
|
||||
type MsgCFHeaders struct {
|
||||
FilterType FilterType
|
||||
StopHash chainhash.Hash
|
||||
PrevFilterHeader chainhash.Hash
|
||||
FilterHashes []*chainhash.Hash
|
||||
}
|
||||
|
||||
// AddCFHash adds a new filter hash to the message.
|
||||
func (msg *MsgCFHeaders) AddCFHash(hash *chainhash.Hash) error {
|
||||
if len(msg.FilterHashes)+1 > MaxCFHeadersPerMsg {
|
||||
str := fmt.Sprintf("too many block headers in message [max %v]",
|
||||
MaxBlockHeadersPerMsg)
|
||||
return messageError("MsgCFHeaders.AddCFHash", str)
|
||||
}
|
||||
|
||||
msg.FilterHashes = append(msg.FilterHashes, hash)
|
||||
return nil
|
||||
}
|
||||
|
||||
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
|
||||
// Read filter type
|
||||
err := readElement(r, &msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read stop hash
|
||||
err = readElement(r, &msg.StopHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read prev filter header
|
||||
err = readElement(r, &msg.PrevFilterHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read number of filter headers
|
||||
count, err := ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Limit to max committed filter headers per message.
|
||||
if count > MaxCFHeadersPerMsg {
|
||||
str := fmt.Sprintf("too many committed filter headers for "+
|
||||
"message [count %v, max %v]", count,
|
||||
MaxBlockHeadersPerMsg)
|
||||
return messageError("MsgCFHeaders.BtcDecode", str)
|
||||
}
|
||||
|
||||
// Create a contiguous slice of hashes to deserialize into in order to
|
||||
// reduce the number of allocations.
|
||||
msg.FilterHashes = make([]*chainhash.Hash, 0, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
var cfh chainhash.Hash
|
||||
err := readElement(r, &cfh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg.AddCFHash(&cfh)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error {
|
||||
// Write filter type
|
||||
err := writeElement(w, msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write stop hash
|
||||
err = writeElement(w, msg.StopHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write prev filter header
|
||||
err = writeElement(w, msg.PrevFilterHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Limit to max committed headers per message.
|
||||
count := len(msg.FilterHashes)
|
||||
if count > MaxCFHeadersPerMsg {
|
||||
str := fmt.Sprintf("too many committed filter headers for "+
|
||||
"message [count %v, max %v]", count,
|
||||
MaxBlockHeadersPerMsg)
|
||||
return messageError("MsgCFHeaders.BtcEncode", str)
|
||||
}
|
||||
|
||||
err = WriteVarInt(w, pver, uint64(count))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, cfh := range msg.FilterHashes {
|
||||
err := writeElement(w, cfh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deserialize decodes a filter header from r into the receiver using a format
|
||||
// that is suitable for long-term storage such as a database. This function
|
||||
// differs from BtcDecode in that BtcDecode decodes from the bitcoin wire
|
||||
// protocol as it was sent across the network. The wire encoding can
|
||||
// technically differ depending on the protocol version and doesn't even really
|
||||
// need to match the format of a stored filter header at all. As of the time
|
||||
// this comment was written, the encoded filter header is the same in both
|
||||
// instances, but there is a distinct difference and separating the two allows
|
||||
// the API to be flexible enough to deal with changes.
|
||||
func (msg *MsgCFHeaders) Deserialize(r io.Reader) error {
|
||||
// At the current time, there is no difference between the wire encoding
|
||||
// and the stable long-term storage format. As a result, make use of
|
||||
// BtcDecode.
|
||||
return msg.BtcDecode(r, 0, BaseEncoding)
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgCFHeaders) Command() string {
|
||||
return CmdCFHeaders
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 {
|
||||
// Hash size + filter type + num headers (varInt) +
|
||||
// (header size * max headers).
|
||||
return 1 + chainhash.HashSize + chainhash.HashSize + MaxVarIntPayload +
|
||||
(MaxCFHeaderPayload * MaxCFHeadersPerMsg)
|
||||
}
|
||||
|
||||
// NewMsgCFHeaders returns a new bitcoin cfheaders message that conforms to
|
||||
// the Message interface. See MsgCFHeaders for details.
|
||||
func NewMsgCFHeaders() *MsgCFHeaders {
|
||||
return &MsgCFHeaders{
|
||||
FilterHashes: make([]*chainhash.Hash, 0, MaxCFHeadersPerMsg),
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2017 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"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// FilterType is used to represent a filter type.
|
||||
type FilterType uint8
|
||||
|
||||
const (
|
||||
// GCSFilterRegular is the regular filter type.
|
||||
GCSFilterRegular FilterType = iota
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxCFilterDataSize is the maximum byte size of a committed filter.
|
||||
// The maximum size is currently defined as 256KiB.
|
||||
MaxCFilterDataSize = 256 * 1024
|
||||
)
|
||||
|
||||
// MsgCFilter implements the Message interface and represents a bitcoin cfilter
|
||||
// message. It is used to deliver a committed filter in response to a
|
||||
// getcfilters (MsgGetCFilters) message.
|
||||
type MsgCFilter struct {
|
||||
FilterType FilterType
|
||||
BlockHash chainhash.Hash
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
|
||||
// Read filter type
|
||||
err := readElement(r, &msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the hash of the filter's block
|
||||
err = readElement(r, &msg.BlockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read filter data
|
||||
msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize,
|
||||
"cfilter data")
|
||||
return err
|
||||
}
|
||||
|
||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error {
|
||||
size := len(msg.Data)
|
||||
if size > MaxCFilterDataSize {
|
||||
str := fmt.Sprintf("cfilter size too large for message "+
|
||||
"[size %v, max %v]", size, MaxCFilterDataSize)
|
||||
return messageError("MsgCFilter.BtcEncode", str)
|
||||
}
|
||||
|
||||
err := writeElement(w, msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeElement(w, msg.BlockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteVarBytes(w, pver, msg.Data)
|
||||
}
|
||||
|
||||
// Deserialize decodes a filter from r into the receiver using a format that is
|
||||
// suitable for long-term storage such as a database. This function differs
|
||||
// from BtcDecode in that BtcDecode decodes from the bitcoin wire protocol as
|
||||
// it was sent across the network. The wire encoding can technically differ
|
||||
// depending on the protocol version and doesn't even really need to match the
|
||||
// format of a stored filter at all. As of the time this comment was written,
|
||||
// the encoded filter is the same in both instances, but there is a distinct
|
||||
// difference and separating the two allows the API to be flexible enough to
|
||||
// deal with changes.
|
||||
func (msg *MsgCFilter) Deserialize(r io.Reader) error {
|
||||
// At the current time, there is no difference between the wire encoding
|
||||
// and the stable long-term storage format. As a result, make use of
|
||||
// BtcDecode.
|
||||
return msg.BtcDecode(r, 0, BaseEncoding)
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgCFilter) Command() string {
|
||||
return CmdCFilter
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 {
|
||||
return uint32(VarIntSerializeSize(MaxCFilterDataSize)) +
|
||||
MaxCFilterDataSize + chainhash.HashSize + 1
|
||||
}
|
||||
|
||||
// NewMsgCFilter returns a new bitcoin cfilter message that conforms to the
|
||||
// Message interface. See MsgCFilter for details.
|
||||
func NewMsgCFilter(filterType FilterType, blockHash *chainhash.Hash,
|
||||
data []byte) *MsgCFilter {
|
||||
return &MsgCFilter{
|
||||
FilterType: filterType,
|
||||
BlockHash: *blockHash,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2018 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 (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// MsgGetCFCheckpt is a request for filter headers at evenly spaced intervals
|
||||
// throughout the blockchain history. It allows to set the FilterType field to
|
||||
// get headers in the chain of basic (0x00) or extended (0x01) headers.
|
||||
type MsgGetCFCheckpt struct {
|
||||
FilterType FilterType
|
||||
StopHash chainhash.Hash
|
||||
}
|
||||
|
||||
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
|
||||
err := readElement(r, &msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return readElement(r, &msg.StopHash)
|
||||
}
|
||||
|
||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error {
|
||||
err := writeElement(w, msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeElement(w, &msg.StopHash)
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgGetCFCheckpt) Command() string {
|
||||
return CmdGetCFCheckpt
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFCheckpt) MaxPayloadLength(pver uint32) uint32 {
|
||||
// Filter type + uint32 + block hash
|
||||
return 1 + chainhash.HashSize
|
||||
}
|
||||
|
||||
// NewMsgGetCFCheckpt returns a new bitcoin getcfcheckpt message that conforms
|
||||
// to the Message interface using the passed parameters and defaults for the
|
||||
// remaining fields.
|
||||
func NewMsgGetCFCheckpt(filterType FilterType, stopHash *chainhash.Hash) *MsgGetCFCheckpt {
|
||||
return &MsgGetCFCheckpt{
|
||||
FilterType: filterType,
|
||||
StopHash: *stopHash,
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2017 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 (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// MsgGetCFHeaders is a message similar to MsgGetHeaders, but for committed
|
||||
// filter headers. It allows to set the FilterType field to get headers in the
|
||||
// chain of basic (0x00) or extended (0x01) headers.
|
||||
type MsgGetCFHeaders struct {
|
||||
FilterType FilterType
|
||||
StartHeight uint32
|
||||
StopHash chainhash.Hash
|
||||
}
|
||||
|
||||
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
|
||||
err := readElement(r, &msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = readElement(r, &msg.StartHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return readElement(r, &msg.StopHash)
|
||||
}
|
||||
|
||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error {
|
||||
err := writeElement(w, msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeElement(w, &msg.StartHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeElement(w, &msg.StopHash)
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgGetCFHeaders) Command() string {
|
||||
return CmdGetCFHeaders
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 {
|
||||
// Filter type + uint32 + block hash
|
||||
return 1 + 4 + chainhash.HashSize
|
||||
}
|
||||
|
||||
// NewMsgGetCFHeaders returns a new bitcoin getcfheader message that conforms to
|
||||
// the Message interface using the passed parameters and defaults for the
|
||||
// remaining fields.
|
||||
func NewMsgGetCFHeaders(filterType FilterType, startHeight uint32,
|
||||
stopHash *chainhash.Hash) *MsgGetCFHeaders {
|
||||
return &MsgGetCFHeaders{
|
||||
FilterType: filterType,
|
||||
StartHeight: startHeight,
|
||||
StopHash: *stopHash,
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2017 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 (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// MaxGetCFiltersReqRange the maximum number of filters that may be requested in
|
||||
// a getcfheaders message.
|
||||
const MaxGetCFiltersReqRange = 1000
|
||||
|
||||
// MsgGetCFilters implements the Message interface and represents a bitcoin
|
||||
// getcfilters message. It is used to request committed filters for a range of
|
||||
// blocks.
|
||||
type MsgGetCFilters struct {
|
||||
FilterType FilterType
|
||||
StartHeight uint32
|
||||
StopHash chainhash.Hash
|
||||
}
|
||||
|
||||
// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFilters) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
|
||||
err := readElement(r, &msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = readElement(r, &msg.StartHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return readElement(r, &msg.StopHash)
|
||||
}
|
||||
|
||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFilters) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error {
|
||||
err := writeElement(w, msg.FilterType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeElement(w, &msg.StartHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeElement(w, &msg.StopHash)
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgGetCFilters) Command() string {
|
||||
return CmdGetCFilters
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgGetCFilters) MaxPayloadLength(pver uint32) uint32 {
|
||||
// Filter type + uint32 + block hash
|
||||
return 1 + 4 + chainhash.HashSize
|
||||
}
|
||||
|
||||
// NewMsgGetCFilters returns a new bitcoin getcfilters message that conforms to
|
||||
// the Message interface using the passed parameters and defaults for the
|
||||
// remaining fields.
|
||||
func NewMsgGetCFilters(filterType FilterType, startHeight uint32,
|
||||
stopHash *chainhash.Hash) *MsgGetCFilters {
|
||||
return &MsgGetCFilters{
|
||||
FilterType: filterType,
|
||||
StartHeight: startHeight,
|
||||
StopHash: *stopHash,
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -78,7 +78,7 @@ func TestGetDataWire(t *testing.T) {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
// Transation 1 of Block 203707 hash.
|
||||
// Transaction 1 of Block 203707 hash.
|
||||
hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
|
||||
txHash, err := chainhash.NewHashFromStr(hashStr)
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ func TestInvWire(t *testing.T) {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
// Transation 1 of Block 203707 hash.
|
||||
// Transaction 1 of Block 203707 hash.
|
||||
hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
|
||||
txHash, err := chainhash.NewHashFromStr(hashStr)
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -405,7 +405,7 @@ var merkleBlockOne = MsgMerkleBlock{
|
||||
}
|
||||
|
||||
// merkleBlockOneBytes is the serialized bytes for a merkle block created from
|
||||
// block one of the block chain where the first transation matches.
|
||||
// block one of the block chain where the first transaction matches.
|
||||
var merkleBlockOneBytes = []byte{
|
||||
0x01, 0x00, 0x00, 0x00, // Version 1
|
||||
0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ func TestNotFoundWire(t *testing.T) {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
// Transation 1 of Block 203707 hash.
|
||||
// Transaction 1 of Block 203707 hash.
|
||||
hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
|
||||
txHash, err := chainhash.NewHashFromStr(hashStr)
|
||||
if err != nil {
|
||||
|
||||
+4
-4
@@ -62,13 +62,13 @@ const (
|
||||
// a transaction which fits into a message could possibly have.
|
||||
maxTxInPerMessage = (MaxMessagePayload / minTxInPayload) + 1
|
||||
|
||||
// minTxOutPayload is the minimum payload size for a transaction output.
|
||||
// MinTxOutPayload is the minimum payload size for a transaction output.
|
||||
// Value 8 bytes + Varint for PkScript length 1 byte.
|
||||
minTxOutPayload = 9
|
||||
MinTxOutPayload = 9
|
||||
|
||||
// maxTxOutPerMessage is the maximum number of transactions outputs that
|
||||
// a transaction which fits into a message could possibly have.
|
||||
maxTxOutPerMessage = (MaxMessagePayload / minTxOutPayload) + 1
|
||||
maxTxOutPerMessage = (MaxMessagePayload / MinTxOutPayload) + 1
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
@@ -923,7 +923,7 @@ func writeOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error
|
||||
// script. It is encoded as a varInt containing the length of the array
|
||||
// followed by the bytes themselves. An error is returned if the length is
|
||||
// greater than the passed maxAllowed parameter which helps protect against
|
||||
// memory exhuastion attacks and forced panics thorugh malformed messages. The
|
||||
// memory exhaustion attacks and forced panics through malformed messages. The
|
||||
// fieldName parameter is only used for the error message so it provides more
|
||||
// context in the error.
|
||||
func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) {
|
||||
|
||||
+24
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// XXX pedro: we will probably need to bump this.
|
||||
const (
|
||||
// ProtocolVersion is the latest protocol version this package supports.
|
||||
ProtocolVersion uint32 = 70013
|
||||
@@ -70,6 +71,21 @@ const (
|
||||
// SFNodeWitness is a flag used to indicate a peer supports blocks
|
||||
// and transactions including witness data (BIP0144).
|
||||
SFNodeWitness
|
||||
|
||||
// SFNodeXthin is a flag used to indicate a peer supports xthin blocks.
|
||||
SFNodeXthin
|
||||
|
||||
// SFNodeBit5 is a flag used to indicate a peer supports a service
|
||||
// defined by bit 5.
|
||||
SFNodeBit5
|
||||
|
||||
// SFNodeCF is a flag used to indicate a peer supports committed
|
||||
// filters (CFs).
|
||||
SFNodeCF
|
||||
|
||||
// SFNode2X is a flag used to indicate a peer is running the Segwit2X
|
||||
// software.
|
||||
SFNode2X
|
||||
)
|
||||
|
||||
// Map of service flags back to their constant names for pretty printing.
|
||||
@@ -78,6 +94,10 @@ var sfStrings = map[ServiceFlag]string{
|
||||
SFNodeGetUTXO: "SFNodeGetUTXO",
|
||||
SFNodeBloom: "SFNodeBloom",
|
||||
SFNodeWitness: "SFNodeWitness",
|
||||
SFNodeXthin: "SFNodeXthin",
|
||||
SFNodeBit5: "SFNodeBit5",
|
||||
SFNodeCF: "SFNodeCF",
|
||||
SFNode2X: "SFNode2X",
|
||||
}
|
||||
|
||||
// orderedSFStrings is an ordered list of service flags from highest to
|
||||
@@ -87,6 +107,10 @@ var orderedSFStrings = []ServiceFlag{
|
||||
SFNodeGetUTXO,
|
||||
SFNodeBloom,
|
||||
SFNodeWitness,
|
||||
SFNodeXthin,
|
||||
SFNodeBit5,
|
||||
SFNodeCF,
|
||||
SFNode2X,
|
||||
}
|
||||
|
||||
// String returns the ServiceFlag in human-readable form.
|
||||
|
||||
+5
-1
@@ -17,7 +17,11 @@ func TestServiceFlagStringer(t *testing.T) {
|
||||
{SFNodeGetUTXO, "SFNodeGetUTXO"},
|
||||
{SFNodeBloom, "SFNodeBloom"},
|
||||
{SFNodeWitness, "SFNodeWitness"},
|
||||
{0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|0xfffffff0"},
|
||||
{SFNodeXthin, "SFNodeXthin"},
|
||||
{SFNodeBit5, "SFNodeBit5"},
|
||||
{SFNodeCF, "SFNodeCF"},
|
||||
{SFNode2X, "SFNode2X"},
|
||||
{0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|SFNodeXthin|SFNodeBit5|SFNodeCF|SFNode2X|0xffffff00"},
|
||||
}
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
|
||||
Reference in New Issue
Block a user