Implemented BIP 0014 format for user agent
the new function AddUserAgent adds the user agent to the stack and formats it as per BIP 0014 e.g: "/btcwire:0.1.4/myclient:1.2.3(optional; comments)/" the validation on UserAgent has been moved to a new function validateUserAgent
This commit is contained in:
parent
a9293bd32e
commit
620cbdeb8e
5 changed files with 75 additions and 23 deletions
|
@ -105,7 +105,6 @@ from a remote peer is:
|
|||
|
||||
## TODO
|
||||
|
||||
- Implement functions for [BIP 0014](https://en.bitcoin.it/wiki/BIP_0014)
|
||||
- Implement alert message decoding/encoding
|
||||
- Implement bloom filter messages (filterload, filteradd, filterclear,
|
||||
merkleblock) as defined in [BIP 0037](https://en.bitcoin.it/wiki/BIP_0037)
|
||||
|
|
1
doc.go
1
doc.go
|
@ -150,6 +150,7 @@ 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)
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ func TestMessage(t *testing.T) {
|
|||
t.Errorf("NewNetAddress: %v", err)
|
||||
}
|
||||
me.Timestamp = time.Time{} // Version message has zero value timestamp.
|
||||
msgVersion := btcwire.NewMsgVersion(me, you, 123123, "/test:0.0.1/", 0)
|
||||
msgVersion := btcwire.NewMsgVersion(me, you, 123123, 0)
|
||||
|
||||
msgVerack := btcwire.NewMsgVerAck()
|
||||
msgGetAddr := btcwire.NewMsgGetAddr()
|
||||
|
@ -76,7 +76,7 @@ func TestMessage(t *testing.T) {
|
|||
btcnet btcwire.BitcoinNet // Network to use for wire encoding
|
||||
bytes int // Expected num bytes read/written
|
||||
}{
|
||||
{msgVersion, msgVersion, pver, btcwire.MainNet, 122},
|
||||
{msgVersion, msgVersion, pver, btcwire.MainNet, 125},
|
||||
{msgVerack, msgVerack, pver, btcwire.MainNet, 24},
|
||||
{msgGetAddr, msgGetAddr, pver, btcwire.MainNet, 24},
|
||||
{msgAddr, msgAddr, pver, btcwire.MainNet, 25},
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -16,6 +17,9 @@ import (
|
|||
// version message (MsgVersion).
|
||||
const MaxUserAgentLen = 2000
|
||||
|
||||
// DefaultUserAgent for btcwire in the stack
|
||||
const DefaultUserAgent = "/btcwire:0.1.4/"
|
||||
|
||||
// MsgVersion implements the Message interface and represents a bitcoin version
|
||||
// message. It is used for a peer to advertise itself as soon as an outbound
|
||||
// connection is made. The remote peer then uses this information along with
|
||||
|
@ -115,10 +119,9 @@ func (msg *MsgVersion) BtcDecode(r io.Reader, pver uint32) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(userAgent) > MaxUserAgentLen {
|
||||
str := fmt.Sprintf("user agent too long [len %v, max %v]",
|
||||
len(userAgent), MaxUserAgentLen)
|
||||
return messageError("MsgVersion.BtcDecode", str)
|
||||
err = validateUserAgent(userAgent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg.UserAgent = userAgent
|
||||
}
|
||||
|
@ -152,13 +155,12 @@ func (msg *MsgVersion) BtcDecode(r io.Reader, pver uint32) error {
|
|||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
func (msg *MsgVersion) BtcEncode(w io.Writer, pver uint32) error {
|
||||
if len(msg.UserAgent) > MaxUserAgentLen {
|
||||
str := fmt.Sprintf("user agent too long [len %v, max %v]",
|
||||
len(msg.UserAgent), MaxUserAgentLen)
|
||||
return messageError("MsgVersion.BtcEncode", str)
|
||||
err := validateUserAgent(msg.UserAgent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := writeElements(w, msg.ProtocolVersion, msg.Services,
|
||||
err = writeElements(w, msg.ProtocolVersion, msg.Services,
|
||||
msg.Timestamp.Unix())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -224,7 +226,7 @@ func (msg *MsgVersion) MaxPayloadLength(pver uint32) uint32 {
|
|||
// Message interface using the passed parameters and defaults for the remaining
|
||||
// fields.
|
||||
func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
|
||||
userAgent string, lastBlock int32) *MsgVersion {
|
||||
lastBlock int32) *MsgVersion {
|
||||
|
||||
// Limit the timestamp to one second precision since the protocol
|
||||
// doesn't support better.
|
||||
|
@ -235,7 +237,7 @@ func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
|
|||
AddrYou: *you,
|
||||
AddrMe: *me,
|
||||
Nonce: nonce,
|
||||
UserAgent: userAgent,
|
||||
UserAgent: DefaultUserAgent,
|
||||
LastBlock: lastBlock,
|
||||
DisableRelayTx: false,
|
||||
}
|
||||
|
@ -244,7 +246,7 @@ func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
|
|||
// NewMsgVersionFromConn is a convenience function that extracts the remote
|
||||
// and local address from conn and returns a new bitcoin version message that
|
||||
// conforms to the Message interface. See NewMsgVersion.
|
||||
func NewMsgVersionFromConn(conn net.Conn, nonce uint64, userAgent string,
|
||||
func NewMsgVersionFromConn(conn net.Conn, nonce uint64,
|
||||
lastBlock int32) (*MsgVersion, error) {
|
||||
|
||||
// Don't assume any services until we know otherwise.
|
||||
|
@ -259,5 +261,33 @@ func NewMsgVersionFromConn(conn net.Conn, nonce uint64, userAgent string,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return NewMsgVersion(lna, rna, nonce, userAgent, lastBlock), nil
|
||||
return NewMsgVersion(lna, rna, nonce, lastBlock), nil
|
||||
}
|
||||
|
||||
// validateUserAgent checks userAgent length against MaxUserAgentLen
|
||||
func validateUserAgent(userAgent string) error {
|
||||
if len(userAgent) > MaxUserAgentLen {
|
||||
str := fmt.Sprintf("user agent too long [len %v, max %v]",
|
||||
len(userAgent), MaxUserAgentLen)
|
||||
return messageError("MsgVersion", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddUserAgent adds a custom user agent
|
||||
func (msg *MsgVersion) AddUserAgent(name string, version string,
|
||||
comments ...string) error {
|
||||
|
||||
newUserAgent := fmt.Sprintf("%s:%s", name, version)
|
||||
if len(comments) != 0 {
|
||||
newUserAgent = fmt.Sprintf("%s(%s)", newUserAgent,
|
||||
strings.Join(comments, "; "))
|
||||
}
|
||||
newUserAgent = fmt.Sprintf("%s%s/", msg.UserAgent, newUserAgent)
|
||||
err := validateUserAgent(newUserAgent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg.UserAgent = newUserAgent
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ func TestVersion(t *testing.T) {
|
|||
pver := btcwire.ProtocolVersion
|
||||
|
||||
// Create version message data.
|
||||
userAgent := "/btcdtest:0.0.1/"
|
||||
lastBlock := int32(234234)
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333}
|
||||
me, err := btcwire.NewNetAddress(tcpAddrMe, btcwire.SFNodeNetwork)
|
||||
|
@ -39,7 +38,7 @@ func TestVersion(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure we get the correct data back out.
|
||||
msg := btcwire.NewMsgVersion(me, you, nonce, userAgent, lastBlock)
|
||||
msg := btcwire.NewMsgVersion(me, you, nonce, lastBlock)
|
||||
if msg.ProtocolVersion != int32(pver) {
|
||||
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
||||
msg.ProtocolVersion, pver)
|
||||
|
@ -56,9 +55,9 @@ func TestVersion(t *testing.T) {
|
|||
t.Errorf("NewMsgVersion: wrong nonce - got %v, want %v",
|
||||
msg.Nonce, nonce)
|
||||
}
|
||||
if msg.UserAgent != userAgent {
|
||||
if msg.UserAgent != btcwire.DefaultUserAgent {
|
||||
t.Errorf("NewMsgVersion: wrong user agent - got %v, want %v",
|
||||
msg.UserAgent, userAgent)
|
||||
msg.UserAgent, btcwire.DefaultUserAgent)
|
||||
}
|
||||
if msg.LastBlock != lastBlock {
|
||||
t.Errorf("NewMsgVersion: wrong last block - got %v, want %v",
|
||||
|
@ -69,6 +68,29 @@ func TestVersion(t *testing.T) {
|
|||
"default - got %v, want %v", msg.DisableRelayTx, false)
|
||||
}
|
||||
|
||||
msg.AddUserAgent("myclient", "1.2.3", "optional", "comments")
|
||||
customUserAgent := btcwire.DefaultUserAgent + "myclient:1.2.3(optional; comments)/"
|
||||
if msg.UserAgent != customUserAgent {
|
||||
t.Errorf("AddUserAgent: wrong user agent - got %s, want %s",
|
||||
msg.UserAgent, customUserAgent)
|
||||
}
|
||||
|
||||
msg.AddUserAgent("mygui", "3.4.5")
|
||||
customUserAgent += "mygui:3.4.5/"
|
||||
if msg.UserAgent != customUserAgent {
|
||||
t.Errorf("AddUserAgent: wrong user agent - got %s, want %s",
|
||||
msg.UserAgent, customUserAgent)
|
||||
}
|
||||
|
||||
// accounting for ":", "/"
|
||||
err = msg.AddUserAgent(strings.Repeat("t",
|
||||
btcwire.MaxUserAgentLen-len(customUserAgent)-2+1), "")
|
||||
if _, ok := err.(*btcwire.MessageError); !ok {
|
||||
t.Errorf("AddUserAgent: expected error not received "+
|
||||
"- got %v, want %T", err, btcwire.MessageError{})
|
||||
|
||||
}
|
||||
|
||||
// Version message should not have any services set by default.
|
||||
if msg.Services != 0 {
|
||||
t.Errorf("NewMsgVersion: wrong default services - got %v, want %v",
|
||||
|
@ -111,7 +133,7 @@ func TestVersion(t *testing.T) {
|
|||
|
||||
// Use a fake connection.
|
||||
conn := &fakeConn{localAddr: tcpAddrMe, remoteAddr: tcpAddrYou}
|
||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, userAgent, lastBlock)
|
||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, lastBlock)
|
||||
if err != nil {
|
||||
t.Errorf("NewMsgVersionFromConn: %v", err)
|
||||
}
|
||||
|
@ -131,7 +153,7 @@ func TestVersion(t *testing.T) {
|
|||
localAddr: &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333},
|
||||
remoteAddr: tcpAddrYou,
|
||||
}
|
||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, userAgent, lastBlock)
|
||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, lastBlock)
|
||||
if err != btcwire.ErrInvalidNetAddr {
|
||||
t.Errorf("NewMsgVersionFromConn: expected error not received "+
|
||||
"- got %v, want %v", err, btcwire.ErrInvalidNetAddr)
|
||||
|
@ -142,7 +164,7 @@ func TestVersion(t *testing.T) {
|
|||
localAddr: tcpAddrMe,
|
||||
remoteAddr: &net.UDPAddr{IP: net.ParseIP("192.168.0.1"), Port: 8333},
|
||||
}
|
||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, userAgent, lastBlock)
|
||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, lastBlock)
|
||||
if err != btcwire.ErrInvalidNetAddr {
|
||||
t.Errorf("NewMsgVersionFromConn: expected error not received "+
|
||||
"- got %v, want %v", err, btcwire.ErrInvalidNetAddr)
|
||||
|
|
Loading…
Reference in a new issue