From 0d375e0738e5995b1c3beb303a654aefe76e4a64 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 6 Apr 2023 18:40:30 -0500 Subject: [PATCH 1/5] [release-v1.7] peer: Support module graph prune and lazy load. This bumps the go directive for the peer module to 1.17 which will allow the new module graph pruning and lazy loading capabilities introduced in Go 1.17 to be used once the updated modules are released. This means that, as described by the documentation, the go.mod file for the module now include a separate require block that includes all of the indirect dependencies. --- peer/go.mod | 12 +++++++++++- peer/go.sum | 1 - 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/peer/go.mod b/peer/go.mod index ee5213718d..518afc866f 100644 --- a/peer/go.mod +++ b/peer/go.mod @@ -1,6 +1,6 @@ module github.com/decred/dcrd/peer/v3 -go 1.11 +go 1.17 require ( github.com/davecgh/go-spew v1.1.1 @@ -11,3 +11,13 @@ require ( github.com/decred/go-socks v1.1.0 github.com/decred/slog v1.2.0 ) + +require ( + github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect + github.com/dchest/siphash v1.2.2 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.1 // indirect + github.com/decred/dcrd/dcrec v1.0.0 // indirect + github.com/decred/dcrd/dcrec/edwards/v2 v2.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect +) diff --git a/peer/go.sum b/peer/go.sum index 1d99529b01..6d03e5d7fd 100644 --- a/peer/go.sum +++ b/peer/go.sum @@ -9,7 +9,6 @@ github.com/decred/base58 v1.0.3/go.mod h1:pXP9cXCfM2sFLb2viz2FNIdeMWmZDBKG3ZBYbi github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= github.com/decred/dcrd/chaincfg/chainhash v1.0.3 h1:PF2czcYZGW3dz4i/35AUfVAgnqHl9TMNQt1ADTYGOoE= github.com/decred/dcrd/chaincfg/chainhash v1.0.3/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= -github.com/decred/dcrd/chaincfg/v3 v3.1.0 h1:u8l+E6ryv8E0WY69pM/lUI36UeAVcLKBwD/Q3xPiuog= github.com/decred/dcrd/chaincfg/v3 v3.1.0/go.mod h1:4XF9nlx2NeGD4xzw1+L0DGICZMl0a5rKV8nnuHLgk8o= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= From 27ff4fa0c06548392966d2f14ed985b0cbe69a40 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 6 Apr 2023 18:43:45 -0500 Subject: [PATCH 2/5] [release-v1.7] peer: Go 1.19 doc comment formatting. This modifies the peer module to use the new formatting of doc comments in the Go 1.19 release. --- peer/doc.go | 78 ++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/peer/doc.go b/peer/doc.go index 138d13c7c2..90b46a39e9 100644 --- a/peer/doc.go +++ b/peer/doc.go @@ -1,5 +1,5 @@ // Copyright (c) 2015-2016 The btcsuite developers -// Copyright (c) 2016-2021 The Decred developers +// Copyright (c) 2016-2022 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -15,37 +15,37 @@ Payment Verification (SPV) nodes, proxies, etc. A quick overview of the major features peer provides are as follows: - - Provides a basic concurrent safe Decred peer for handling decred - communications via the peer-to-peer protocol - - Full duplex reading and writing of Decred protocol messages - - Automatic handling of the initial handshake process including protocol - version negotiation - - Asynchronous message queuing of outbound messages with optional channel for - notification when the message is actually sent - - Flexible peer configuration - - Caller is responsible for creating outgoing connections and listening for - incoming connections so they have flexibility to establish connections as - they see fit (proxies, etc) - - User agent name and version - - Decred network - - Service support signalling (full nodes, etc) - - Maximum supported protocol version - - Ability to register callbacks for handling Decred protocol messages - - Inventory message batching and send trickling with known inventory detection - and avoidance - - Automatic periodic keep-alive pinging and pong responses - - Random nonce generation and self connection detection - - Snapshottable peer statistics such as the total number of bytes read and - written, the remote address, user agent, and negotiated protocol version - - Helper functions pushing addresses, getblocks, getheaders, and reject - messages - - These could all be sent manually via the standard message output function, - but the helpers provide additional nice functionality such as duplicate - filtering and address randomization - - Ability to wait for shutdown/disconnect - - Comprehensive test coverage - -Peer Configuration + - Provides a basic concurrent safe Decred peer for handling decred + communications via the peer-to-peer protocol + - Full duplex reading and writing of Decred protocol messages + - Automatic handling of the initial handshake process including protocol + version negotiation + - Asynchronous message queuing of outbound messages with optional channel for + notification when the message is actually sent + - Flexible peer configuration + - Caller is responsible for creating outgoing connections and listening for + incoming connections so they have flexibility to establish connections as + they see fit (proxies, etc) + - User agent name and version + - Decred network + - Service support signalling (full nodes, etc) + - Maximum supported protocol version + - Ability to register callbacks for handling Decred protocol messages + - Inventory message batching and send trickling with known inventory detection + and avoidance + - Automatic periodic keep-alive pinging and pong responses + - Random nonce generation and self connection detection + - Snapshottable peer statistics such as the total number of bytes read and + written, the remote address, user agent, and negotiated protocol version + - Helper functions pushing addresses, getblocks, getheaders, and reject + messages + - The aforementioned messages could all be sent manually via the standard + message output function, but the helpers provide additional nice + functionality such as duplicate filtering and address randomization + - Ability to wait for shutdown/disconnect + - Comprehensive test coverage + +# Peer Configuration All peer configuration is handled with the Config struct. This allows the caller to specify things such as the user agent name and version, the decred @@ -53,7 +53,7 @@ network to use, which services it supports, and callbacks to invoke when decred messages are received. See the documentation for each field of the Config struct for more details. -Inbound and Outbound Peers +# Inbound and Outbound Peers A peer can either be inbound or outbound. The caller is responsible for establishing the connection to remote peers and listening for incoming peers. @@ -68,7 +68,7 @@ Disconnect to disconnect from the peer and clean up all resources. WaitForDisconnect can be used to block until peer disconnection and resource cleanup has completed. -Callbacks +# Callbacks In order to do anything useful with a peer, it is necessary to react to decred messages. This is accomplished by creating an instance of the MessageListeners @@ -87,7 +87,7 @@ It is often useful to use closures which encapsulate state when specifying the callback handlers. This provides a clean method for accessing that state when callbacks are invoked. -Queuing Messages and Inventory +# Queuing Messages and Inventory The QueueMessage function provides the fundamental means to send messages to the remote peer. As the name implies, this employs a non-blocking queue. A done @@ -101,7 +101,7 @@ QueueInventory function. It employs batching and trickling along with intelligent known remote peer inventory detection and avoidance through the use of a most-recently used algorithm. -Message Sending Helper Functions +# Message Sending Helper Functions In addition to the bare QueueMessage function previously described, the PushAddrMsg, PushGetBlocksMsg, and PushGetHeadersMsg functions are provided as a @@ -119,13 +119,13 @@ Finally, the PushGetBlocksMsg and PushGetHeadersMsg functions will construct proper messages using a block locator and ignore back to back duplicate requests. -Peer Statistics +# Peer Statistics A snapshot of the current peer statistics can be obtained with the StatsSnapshot function. This includes statistics such as the total number of bytes read and written, the remote address, user agent, and negotiated protocol version. -Logging +# Logging This package provides extensive logging capabilities through the UseLogger function which allows a slog.Logger to be specified. For example, logging at @@ -133,7 +133,7 @@ the debug level provides summaries of every message sent and received, and logging at the trace level provides full dumps of parsed messages as well as the raw message bytes using a format similar to hexdump -C. -Improvement Proposals +# Improvement Proposals This package supports all improvement proposals supported by the wire package. */ From ad501373e203aeff56e8f7f699ab442f8706694e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 21 Nov 2022 14:48:05 -0600 Subject: [PATCH 3/5] [release-v1.7] peer: Use latest pver by default. This updates the max and default protocol version the peer package uses to the latest protocol version (wire.RemoveRejectVersion) and updates the tests to account for the removal of the reject message. It also adds a test that explicitly tests the handler on older protocol versions since the associated message is no longer sent on the latest one. --- peer/peer.go | 2 +- peer/peer_test.go | 76 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index 3562f02f7f..c68f95b813 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -27,7 +27,7 @@ import ( const ( // MaxProtocolVersion is the max protocol version the peer supports. - MaxProtocolVersion = wire.InitStateVersion + MaxProtocolVersion = wire.RemoveRejectVersion // outputBufferSize is the number of elements the output channels use. outputBufferSize = 5000 diff --git a/peer/peer_test.go b/peer/peer_test.go index c32e3c7b68..003115ec20 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -552,10 +552,6 @@ func TestPeerListeners(t *testing.T) { }, // only one version message is allowed // only one verack message is allowed - { - "OnReject", - wire.NewMsgReject("block", wire.RejectDuplicate, "dupe block"), - }, { "OnSendHeaders", wire.NewMsgSendHeaders(), @@ -584,6 +580,78 @@ func TestPeerListeners(t *testing.T) { outPeer.Disconnect() } +// TestDeprecatedRejectListener ensures that the deprecated on reject listener +// is called as expected on older protocol versions. +func TestDeprecatedRejectListener(t *testing.T) { + version := make(chan wire.Message, 1) + verack := make(chan struct{}, 1) + reject := make(chan wire.Message, 20) + peerCfg := &Config{ + ProtocolVersion: wire.RemoveRejectVersion - 1, + Listeners: MessageListeners{ + OnVersion: func(p *Peer, msg *wire.MsgVersion) { + version <- msg + }, + OnVerAck: func(p *Peer, msg *wire.MsgVerAck) { + verack <- struct{}{} + }, + OnReject: func(p *Peer, msg *wire.MsgReject) { + reject <- msg + }, + }, + UserAgentName: "peer", + UserAgentVersion: "1.0", + Net: wire.MainNet, + Services: wire.SFNodeNetwork, + } + inConn, outConn := pipe( + &conn{raddr: "10.0.0.1:8333"}, + &conn{raddr: "10.0.0.2:8333"}, + ) + inPeer := NewInboundPeer(peerCfg) + inPeer.AssociateConnection(inConn) + defer inPeer.Disconnect() + + peerCfg.Listeners = MessageListeners{ + OnVerAck: func(p *Peer, msg *wire.MsgVerAck) { + verack <- struct{}{} + }, + } + outPeer, err := NewOutboundPeer(peerCfg, "10.0.0.1:8333") + if err != nil { + t.Errorf("NewOutboundPeer: unexpected err %v\n", err) + return + } + outPeer.AssociateConnection(outConn) + defer outPeer.Disconnect() + + for i := 0; i < 2; i++ { + select { + case <-verack: + case <-time.After(time.Second * 1): + t.Error("TestPeerListeners: verack timeout\n") + return + } + } + + select { + case <-version: + case <-time.After(time.Second * 1): + t.Error("TestPeerListeners: version timeout") + return + } + + // Queue the reject message. + msg := wire.NewMsgReject("block", wire.RejectDuplicate, "dupe block") + outPeer.QueueMessage(msg, nil) + select { + case <-reject: + case <-time.After(time.Second * 1): + t.Error("TestPeerListeners: OnReject timeout") + return + } +} + // TestOutboundPeer tests that the outbound peer works as expected. func TestOutboundPeer(t *testing.T) { peerCfg := &Config{ From d03fcbe198831981f2184b5e582f06d6caee9c37 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 7 Mar 2023 21:15:27 -0600 Subject: [PATCH 4/5] [release-v1.7] peer: Correct known inventory check. This updates AddKnownInventory and IsKnownInventory to use the concrete struct as opposed to a pointer to it in order to allow different instances of the struct to be used as a key versus needing to check with the same instance. --- peer/peer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index c68f95b813..57d793d933 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -500,7 +500,7 @@ func (p *Peer) UpdateLastBlockHeight(newHeight int64) { // // This function is safe for concurrent access. func (p *Peer) AddKnownInventory(invVect *wire.InvVect) { - p.knownInventory.Add(invVect) + p.knownInventory.Add(*invVect) } // IsKnownInventory returns whether the passed inventory already exists in @@ -508,7 +508,7 @@ func (p *Peer) AddKnownInventory(invVect *wire.InvVect) { // // This function is safe for concurrent access. func (p *Peer) IsKnownInventory(invVect *wire.InvVect) bool { - return p.knownInventory.Contains(invVect) + return p.knownInventory.Contains(*invVect) } // StatsSnapshot returns a snapshot of the current peer flags and statistics. From f3be674564299102e0ce05b5000bac4a7a94bcec Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 6 Apr 2023 18:49:48 -0500 Subject: [PATCH 5/5] [release-v1.7] main: Use backported peer updates. This updates the 1.7 release to use the latest version of the peer module which includes updates to use the latest protocol version by default and reduces bandwidth usage in certain scenarios by avoiding requests for inventory that is already known. In particular, the following updated module version is used: - github.com/decred/dcrd/peer/v3@v3.0.1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8a55b7ae7c..92eb564fda 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/decred/dcrd/hdkeychain/v3 v3.1.0 github.com/decred/dcrd/lru v1.1.1 github.com/decred/dcrd/math/uint256 v1.0.0 - github.com/decred/dcrd/peer/v3 v3.0.0 + github.com/decred/dcrd/peer/v3 v3.0.1 github.com/decred/dcrd/rpc/jsonrpc/types/v3 v3.0.0 github.com/decred/dcrd/rpcclient/v7 v7.0.0 github.com/decred/dcrd/txscript/v4 v4.0.0 diff --git a/go.sum b/go.sum index a0681ace67..df2fc32784 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/decred/dcrd/lru v1.1.1 h1:kWFDaW0OWx6AD6Ki342c+JPmHbiVdE6rK81pT3fuo/Y github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/decred/dcrd/math/uint256 v1.0.0 h1:RGXQ8WzTMZ1eVeXy5uE67DPMB5Aa8N7qjgBNGlHdIQ0= github.com/decred/dcrd/math/uint256 v1.0.0/go.mod h1:s81c06+/jRj3z/Bd73FH79O7nDfOqt1amqtuAnG1cRg= -github.com/decred/dcrd/peer/v3 v3.0.0 h1:tW7UPsHX1569Jh7txpXs2TyXmRFIlgabkBJvN/eHVVY= -github.com/decred/dcrd/peer/v3 v3.0.0/go.mod h1:XF7IR19geyX7hRAyUviyAoU3uyA42vk0YjXWs84V/dU= +github.com/decred/dcrd/peer/v3 v3.0.1 h1:X42CdOQMJ9Kky7XFf0iSNmzT0orxsJviTQP+aU+leJU= +github.com/decred/dcrd/peer/v3 v3.0.1/go.mod h1:LFE32n5WnQ4E9muO2Zf9tHyZmTIBasfOdIc/L1PQjVQ= github.com/decred/dcrd/rpc/jsonrpc/types/v3 v3.0.0 h1:WzG2IARR6OghjhWdxfUbXSPE4GEF2hZlCE5y2L/45f4= github.com/decred/dcrd/rpc/jsonrpc/types/v3 v3.0.0/go.mod h1:1ILDxMKVS/qY71MylpZzuEX4O0u1SON4RPKbaZP71K0= github.com/decred/dcrd/rpcclient/v7 v7.0.0 h1:1XuGWpyjOPMscpwSDuumWTnfLl94LbIqg+5X6uCPYeY=