mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
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
@ -105,7 +105,6 @@ from a remote peer is:
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- Implement functions for [BIP 0014](https://en.bitcoin.it/wiki/BIP_0014)
|
|
||||||
- Implement alert message decoding/encoding
|
- Implement alert message decoding/encoding
|
||||||
- Implement bloom filter messages (filterload, filteradd, filterclear,
|
- Implement bloom filter messages (filterload, filteradd, filterclear,
|
||||||
merkleblock) as defined in [BIP 0037](https://en.bitcoin.it/wiki/BIP_0037)
|
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:
|
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)
|
BIP0031 (https://en.bitcoin.it/wiki/BIP_0031)
|
||||||
BIP0035 (https://en.bitcoin.it/wiki/BIP_0035)
|
BIP0035 (https://en.bitcoin.it/wiki/BIP_0035)
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func TestMessage(t *testing.T) {
|
|||||||
t.Errorf("NewNetAddress: %v", err)
|
t.Errorf("NewNetAddress: %v", err)
|
||||||
}
|
}
|
||||||
me.Timestamp = time.Time{} // Version message has zero value timestamp.
|
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()
|
msgVerack := btcwire.NewMsgVerAck()
|
||||||
msgGetAddr := btcwire.NewMsgGetAddr()
|
msgGetAddr := btcwire.NewMsgGetAddr()
|
||||||
@ -76,7 +76,7 @@ func TestMessage(t *testing.T) {
|
|||||||
btcnet btcwire.BitcoinNet // Network to use for wire encoding
|
btcnet btcwire.BitcoinNet // Network to use for wire encoding
|
||||||
bytes int // Expected num bytes read/written
|
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},
|
{msgVerack, msgVerack, pver, btcwire.MainNet, 24},
|
||||||
{msgGetAddr, msgGetAddr, pver, btcwire.MainNet, 24},
|
{msgGetAddr, msgGetAddr, pver, btcwire.MainNet, 24},
|
||||||
{msgAddr, msgAddr, pver, btcwire.MainNet, 25},
|
{msgAddr, msgAddr, pver, btcwire.MainNet, 25},
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,6 +17,9 @@ import (
|
|||||||
// version message (MsgVersion).
|
// version message (MsgVersion).
|
||||||
const MaxUserAgentLen = 2000
|
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
|
// 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
|
// 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
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(userAgent) > MaxUserAgentLen {
|
err = validateUserAgent(userAgent)
|
||||||
str := fmt.Sprintf("user agent too long [len %v, max %v]",
|
if err != nil {
|
||||||
len(userAgent), MaxUserAgentLen)
|
return err
|
||||||
return messageError("MsgVersion.BtcDecode", str)
|
|
||||||
}
|
}
|
||||||
msg.UserAgent = userAgent
|
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.
|
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||||
// This is part of the Message interface implementation.
|
// This is part of the Message interface implementation.
|
||||||
func (msg *MsgVersion) BtcEncode(w io.Writer, pver uint32) error {
|
func (msg *MsgVersion) BtcEncode(w io.Writer, pver uint32) error {
|
||||||
if len(msg.UserAgent) > MaxUserAgentLen {
|
err := validateUserAgent(msg.UserAgent)
|
||||||
str := fmt.Sprintf("user agent too long [len %v, max %v]",
|
if err != nil {
|
||||||
len(msg.UserAgent), MaxUserAgentLen)
|
return err
|
||||||
return messageError("MsgVersion.BtcEncode", str)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := writeElements(w, msg.ProtocolVersion, msg.Services,
|
err = writeElements(w, msg.ProtocolVersion, msg.Services,
|
||||||
msg.Timestamp.Unix())
|
msg.Timestamp.Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -224,7 +226,7 @@ func (msg *MsgVersion) MaxPayloadLength(pver uint32) uint32 {
|
|||||||
// Message interface using the passed parameters and defaults for the remaining
|
// Message interface using the passed parameters and defaults for the remaining
|
||||||
// fields.
|
// fields.
|
||||||
func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
|
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
|
// Limit the timestamp to one second precision since the protocol
|
||||||
// doesn't support better.
|
// doesn't support better.
|
||||||
@ -235,7 +237,7 @@ func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
|
|||||||
AddrYou: *you,
|
AddrYou: *you,
|
||||||
AddrMe: *me,
|
AddrMe: *me,
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
UserAgent: userAgent,
|
UserAgent: DefaultUserAgent,
|
||||||
LastBlock: lastBlock,
|
LastBlock: lastBlock,
|
||||||
DisableRelayTx: false,
|
DisableRelayTx: false,
|
||||||
}
|
}
|
||||||
@ -244,7 +246,7 @@ func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
|
|||||||
// NewMsgVersionFromConn is a convenience function that extracts the remote
|
// NewMsgVersionFromConn is a convenience function that extracts the remote
|
||||||
// and local address from conn and returns a new bitcoin version message that
|
// and local address from conn and returns a new bitcoin version message that
|
||||||
// conforms to the Message interface. See NewMsgVersion.
|
// 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) {
|
lastBlock int32) (*MsgVersion, error) {
|
||||||
|
|
||||||
// Don't assume any services until we know otherwise.
|
// 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 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
|
pver := btcwire.ProtocolVersion
|
||||||
|
|
||||||
// Create version message data.
|
// Create version message data.
|
||||||
userAgent := "/btcdtest:0.0.1/"
|
|
||||||
lastBlock := int32(234234)
|
lastBlock := int32(234234)
|
||||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333}
|
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333}
|
||||||
me, err := btcwire.NewNetAddress(tcpAddrMe, btcwire.SFNodeNetwork)
|
me, err := btcwire.NewNetAddress(tcpAddrMe, btcwire.SFNodeNetwork)
|
||||||
@ -39,7 +38,7 @@ func TestVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we get the correct data back out.
|
// 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) {
|
if msg.ProtocolVersion != int32(pver) {
|
||||||
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
||||||
msg.ProtocolVersion, pver)
|
msg.ProtocolVersion, pver)
|
||||||
@ -56,9 +55,9 @@ func TestVersion(t *testing.T) {
|
|||||||
t.Errorf("NewMsgVersion: wrong nonce - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong nonce - got %v, want %v",
|
||||||
msg.Nonce, nonce)
|
msg.Nonce, nonce)
|
||||||
}
|
}
|
||||||
if msg.UserAgent != userAgent {
|
if msg.UserAgent != btcwire.DefaultUserAgent {
|
||||||
t.Errorf("NewMsgVersion: wrong user agent - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong user agent - got %v, want %v",
|
||||||
msg.UserAgent, userAgent)
|
msg.UserAgent, btcwire.DefaultUserAgent)
|
||||||
}
|
}
|
||||||
if msg.LastBlock != lastBlock {
|
if msg.LastBlock != lastBlock {
|
||||||
t.Errorf("NewMsgVersion: wrong last block - got %v, want %v",
|
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)
|
"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.
|
// Version message should not have any services set by default.
|
||||||
if msg.Services != 0 {
|
if msg.Services != 0 {
|
||||||
t.Errorf("NewMsgVersion: wrong default services - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong default services - got %v, want %v",
|
||||||
@ -111,7 +133,7 @@ func TestVersion(t *testing.T) {
|
|||||||
|
|
||||||
// Use a fake connection.
|
// Use a fake connection.
|
||||||
conn := &fakeConn{localAddr: tcpAddrMe, remoteAddr: tcpAddrYou}
|
conn := &fakeConn{localAddr: tcpAddrMe, remoteAddr: tcpAddrYou}
|
||||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, userAgent, lastBlock)
|
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, lastBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("NewMsgVersionFromConn: %v", err)
|
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},
|
localAddr: &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333},
|
||||||
remoteAddr: tcpAddrYou,
|
remoteAddr: tcpAddrYou,
|
||||||
}
|
}
|
||||||
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, userAgent, lastBlock)
|
msg, err = btcwire.NewMsgVersionFromConn(conn, nonce, lastBlock)
|
||||||
if err != btcwire.ErrInvalidNetAddr {
|
if err != btcwire.ErrInvalidNetAddr {
|
||||||
t.Errorf("NewMsgVersionFromConn: expected error not received "+
|
t.Errorf("NewMsgVersionFromConn: expected error not received "+
|
||||||
"- got %v, want %v", err, btcwire.ErrInvalidNetAddr)
|
"- got %v, want %v", err, btcwire.ErrInvalidNetAddr)
|
||||||
@ -142,7 +164,7 @@ func TestVersion(t *testing.T) {
|
|||||||
localAddr: tcpAddrMe,
|
localAddr: tcpAddrMe,
|
||||||
remoteAddr: &net.UDPAddr{IP: net.ParseIP("192.168.0.1"), Port: 8333},
|
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 {
|
if err != btcwire.ErrInvalidNetAddr {
|
||||||
t.Errorf("NewMsgVersionFromConn: expected error not received "+
|
t.Errorf("NewMsgVersionFromConn: expected error not received "+
|
||||||
"- got %v, want %v", err, btcwire.ErrInvalidNetAddr)
|
"- got %v, want %v", err, btcwire.ErrInvalidNetAddr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user