mirror of
https://github.com/muun/recovery.git
synced 2025-11-10 05:59:44 -05:00
Release v0.1.0
This commit is contained in:
73
vendor/github.com/btcsuite/btcd/peer/README.md
generated
vendored
Normal file
73
vendor/github.com/btcsuite/btcd/peer/README.md
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
peer
|
||||
====
|
||||
|
||||
[](https://travis-ci.org/btcsuite/btcd)
|
||||
[](http://copyfree.org)
|
||||
[](http://godoc.org/github.com/btcsuite/btcd/peer)
|
||||
|
||||
Package peer provides a common base for creating and managing bitcoin network
|
||||
peers.
|
||||
|
||||
This package has intentionally been designed so it can be used as a standalone
|
||||
package for any projects needing a full featured bitcoin peer base to build on.
|
||||
|
||||
## Overview
|
||||
|
||||
This package builds upon the wire package, which provides the fundamental
|
||||
primitives necessary to speak the bitcoin wire protocol, in order to simplify
|
||||
the process of creating fully functional peers. In essence, it provides a
|
||||
common base for creating concurrent safe fully validating nodes, Simplified
|
||||
Payment Verification (SPV) nodes, proxies, etc.
|
||||
|
||||
A quick overview of the major features peer provides are as follows:
|
||||
|
||||
- Provides a basic concurrent safe bitcoin peer for handling bitcoin
|
||||
communications via the peer-to-peer protocol
|
||||
- Full duplex reading and writing of bitcoin protocol messages
|
||||
- Automatic handling of the initial handshake process including protocol
|
||||
version negotiation
|
||||
- Asynchronous message queueing 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
|
||||
- Bitcoin network
|
||||
- Service support signalling (full nodes, bloom filters, etc)
|
||||
- Maximum supported protocol version
|
||||
- Ability to register callbacks for handling bitcoin 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
|
||||
- Proper handling of bloom filter related commands when the caller does not
|
||||
specify the related flag to signal support
|
||||
- Disconnects the peer when the protocol version is high enough
|
||||
- Does not invoke the related callbacks for older protocol versions
|
||||
- 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
|
||||
|
||||
## Installation and Updating
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/btcsuite/btcd/peer
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
* [New Outbound Peer Example](https://godoc.org/github.com/btcsuite/btcd/peer#example-package--NewOutboundPeer)
|
||||
Demonstrates the basic process for initializing and creating an outbound peer.
|
||||
Peers negotiate by exchanging version and verack messages. For demonstration,
|
||||
a simple handler for the version message is attached to the peer.
|
||||
|
||||
## License
|
||||
|
||||
Package peer is licensed under the [copyfree](http://copyfree.org) ISC License.
|
||||
150
vendor/github.com/btcsuite/btcd/peer/doc.go
generated
vendored
Normal file
150
vendor/github.com/btcsuite/btcd/peer/doc.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2015-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package peer provides a common base for creating and managing Bitcoin network
|
||||
peers.
|
||||
|
||||
Overview
|
||||
|
||||
This package builds upon the wire package, which provides the fundamental
|
||||
primitives necessary to speak the bitcoin wire protocol, in order to simplify
|
||||
the process of creating fully functional peers. In essence, it provides a
|
||||
common base for creating concurrent safe fully validating nodes, Simplified
|
||||
Payment Verification (SPV) nodes, proxies, etc.
|
||||
|
||||
A quick overview of the major features peer provides are as follows:
|
||||
|
||||
- Provides a basic concurrent safe bitcoin peer for handling bitcoin
|
||||
communications via the peer-to-peer protocol
|
||||
- Full duplex reading and writing of bitcoin 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
|
||||
- Bitcoin network
|
||||
- Service support signalling (full nodes, bloom filters, etc)
|
||||
- Maximum supported protocol version
|
||||
- Ability to register callbacks for handling bitcoin 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
|
||||
- Proper handling of bloom filter related commands when the caller does not
|
||||
specify the related flag to signal support
|
||||
- Disconnects the peer when the protocol version is high enough
|
||||
- Does not invoke the related callbacks for older protocol versions
|
||||
- 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
|
||||
|
||||
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 bitcoin
|
||||
network to use, which services it supports, and callbacks to invoke when bitcoin
|
||||
messages are received. See the documentation for each field of the Config
|
||||
struct for more details.
|
||||
|
||||
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.
|
||||
This provides high flexibility for things such as connecting via proxies, acting
|
||||
as a proxy, creating bridge peers, choosing whether to listen for inbound peers,
|
||||
etc.
|
||||
|
||||
NewOutboundPeer and NewInboundPeer functions must be followed by calling Connect
|
||||
with a net.Conn instance to the peer. This will start all async I/O goroutines
|
||||
and initiate the protocol negotiation process. Once finished with the peer call
|
||||
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
|
||||
|
||||
In order to do anything useful with a peer, it is necessary to react to bitcoin
|
||||
messages. This is accomplished by creating an instance of the MessageListeners
|
||||
struct with the callbacks to be invoke specified and setting the Listeners field
|
||||
of the Config struct specified when creating a peer to it.
|
||||
|
||||
For convenience, a callback hook for all of the currently supported bitcoin
|
||||
messages is exposed which receives the peer instance and the concrete message
|
||||
type. In addition, a hook for OnRead is provided so even custom messages types
|
||||
for which this package does not directly provide a hook, as long as they
|
||||
implement the wire.Message interface, can be used. Finally, the OnWrite hook
|
||||
is provided, which in conjunction with OnRead, can be used to track server-wide
|
||||
byte counts.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
channel which will be notified when the message is actually sent can optionally
|
||||
be specified. There are certain message types which are better sent using other
|
||||
functions which provide additional functionality.
|
||||
|
||||
Of special interest are inventory messages. Rather than manually sending MsgInv
|
||||
messages via Queuemessage, the inventory vectors should be queued using the
|
||||
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
|
||||
|
||||
In addition to the bare QueueMessage function previously described, the
|
||||
PushAddrMsg, PushGetBlocksMsg, PushGetHeadersMsg, and PushRejectMsg functions
|
||||
are provided as a convenience. While it is of course possible to create and
|
||||
send these message manually via QueueMessage, these helper functions provided
|
||||
additional useful functionality that is typically desired.
|
||||
|
||||
For example, the PushAddrMsg function automatically limits the addresses to the
|
||||
maximum number allowed by the message and randomizes the chosen addresses when
|
||||
there are too many. This allows the caller to simply provide a slice of known
|
||||
addresses, such as that returned by the addrmgr package, without having to worry
|
||||
about the details.
|
||||
|
||||
Next, the PushGetBlocksMsg and PushGetHeadersMsg functions will construct proper
|
||||
messages using a block locator and ignore back to back duplicate requests.
|
||||
|
||||
Finally, the PushRejectMsg function can be used to easily create and send an
|
||||
appropriate reject message based on the provided parameters as well as
|
||||
optionally provides a flag to cause it to block until the message is actually
|
||||
sent.
|
||||
|
||||
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
|
||||
|
||||
This package provides extensive logging capabilities through the UseLogger
|
||||
function which allows a btclog.Logger to be specified. For example, logging at
|
||||
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.
|
||||
|
||||
Bitcoin Improvement Proposals
|
||||
|
||||
This package supports all BIPS supported by the wire package.
|
||||
(https://godoc.org/github.com/btcsuite/btcd/wire#hdr-Bitcoin_Improvement_Proposals)
|
||||
*/
|
||||
package peer
|
||||
227
vendor/github.com/btcsuite/btcd/peer/log.go
generated
vendored
Normal file
227
vendor/github.com/btcsuite/btcd/peer/log.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
// Copyright (c) 2015-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package peer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btclog"
|
||||
)
|
||||
|
||||
const (
|
||||
// maxRejectReasonLen is the maximum length of a sanitized reject reason
|
||||
// that will be logged.
|
||||
maxRejectReasonLen = 250
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
DisableLog()
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled
|
||||
// by default until UseLogger is called.
|
||||
func DisableLog() {
|
||||
log = btclog.Disabled
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
||||
|
||||
// LogClosure is a closure that can be printed with %v to be used to
|
||||
// generate expensive-to-create data for a detailed log level and avoid doing
|
||||
// the work if the data isn't printed.
|
||||
type logClosure func() string
|
||||
|
||||
func (c logClosure) String() string {
|
||||
return c()
|
||||
}
|
||||
|
||||
func newLogClosure(c func() string) logClosure {
|
||||
return logClosure(c)
|
||||
}
|
||||
|
||||
// directionString is a helper function that returns a string that represents
|
||||
// the direction of a connection (inbound or outbound).
|
||||
func directionString(inbound bool) string {
|
||||
if inbound {
|
||||
return "inbound"
|
||||
}
|
||||
return "outbound"
|
||||
}
|
||||
|
||||
// formatLockTime returns a transaction lock time as a human-readable string.
|
||||
func formatLockTime(lockTime uint32) string {
|
||||
// The lock time field of a transaction is either a block height at
|
||||
// which the transaction is finalized or a timestamp depending on if the
|
||||
// value is before the lockTimeThreshold. When it is under the
|
||||
// threshold it is a block height.
|
||||
if lockTime < txscript.LockTimeThreshold {
|
||||
return fmt.Sprintf("height %d", lockTime)
|
||||
}
|
||||
|
||||
return time.Unix(int64(lockTime), 0).String()
|
||||
}
|
||||
|
||||
// invSummary returns an inventory message as a human-readable string.
|
||||
func invSummary(invList []*wire.InvVect) string {
|
||||
// No inventory.
|
||||
invLen := len(invList)
|
||||
if invLen == 0 {
|
||||
return "empty"
|
||||
}
|
||||
|
||||
// One inventory item.
|
||||
if invLen == 1 {
|
||||
iv := invList[0]
|
||||
switch iv.Type {
|
||||
case wire.InvTypeError:
|
||||
return fmt.Sprintf("error %s", iv.Hash)
|
||||
case wire.InvTypeWitnessBlock:
|
||||
return fmt.Sprintf("witness block %s", iv.Hash)
|
||||
case wire.InvTypeBlock:
|
||||
return fmt.Sprintf("block %s", iv.Hash)
|
||||
case wire.InvTypeWitnessTx:
|
||||
return fmt.Sprintf("witness tx %s", iv.Hash)
|
||||
case wire.InvTypeTx:
|
||||
return fmt.Sprintf("tx %s", iv.Hash)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("unknown (%d) %s", uint32(iv.Type), iv.Hash)
|
||||
}
|
||||
|
||||
// More than one inv item.
|
||||
return fmt.Sprintf("size %d", invLen)
|
||||
}
|
||||
|
||||
// locatorSummary returns a block locator as a human-readable string.
|
||||
func locatorSummary(locator []*chainhash.Hash, stopHash *chainhash.Hash) string {
|
||||
if len(locator) > 0 {
|
||||
return fmt.Sprintf("locator %s, stop %s", locator[0], stopHash)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("no locator, stop %s", stopHash)
|
||||
|
||||
}
|
||||
|
||||
// sanitizeString strips any characters which are even remotely dangerous, such
|
||||
// as html control characters, from the passed string. It also limits it to
|
||||
// the passed maximum size, which can be 0 for unlimited. When the string is
|
||||
// limited, it will also add "..." to the string to indicate it was truncated.
|
||||
func sanitizeString(str string, maxLength uint) string {
|
||||
const safeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY" +
|
||||
"Z01234567890 .,;_/:?@"
|
||||
|
||||
// Strip any characters not in the safeChars string removed.
|
||||
str = strings.Map(func(r rune) rune {
|
||||
if strings.ContainsRune(safeChars, r) {
|
||||
return r
|
||||
}
|
||||
return -1
|
||||
}, str)
|
||||
|
||||
// Limit the string to the max allowed length.
|
||||
if maxLength > 0 && uint(len(str)) > maxLength {
|
||||
str = str[:maxLength]
|
||||
str = str + "..."
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// messageSummary returns a human-readable string which summarizes a message.
|
||||
// Not all messages have or need a summary. This is used for debug logging.
|
||||
func messageSummary(msg wire.Message) string {
|
||||
switch msg := msg.(type) {
|
||||
case *wire.MsgVersion:
|
||||
return fmt.Sprintf("agent %s, pver %d, block %d",
|
||||
msg.UserAgent, msg.ProtocolVersion, msg.LastBlock)
|
||||
|
||||
case *wire.MsgVerAck:
|
||||
// No summary.
|
||||
|
||||
case *wire.MsgGetAddr:
|
||||
// No summary.
|
||||
|
||||
case *wire.MsgAddr:
|
||||
return fmt.Sprintf("%d addr", len(msg.AddrList))
|
||||
|
||||
case *wire.MsgPing:
|
||||
// No summary - perhaps add nonce.
|
||||
|
||||
case *wire.MsgPong:
|
||||
// No summary - perhaps add nonce.
|
||||
|
||||
case *wire.MsgAlert:
|
||||
// No summary.
|
||||
|
||||
case *wire.MsgMemPool:
|
||||
// No summary.
|
||||
|
||||
case *wire.MsgTx:
|
||||
return fmt.Sprintf("hash %s, %d inputs, %d outputs, lock %s",
|
||||
msg.TxHash(), len(msg.TxIn), len(msg.TxOut),
|
||||
formatLockTime(msg.LockTime))
|
||||
|
||||
case *wire.MsgBlock:
|
||||
header := &msg.Header
|
||||
return fmt.Sprintf("hash %s, ver %d, %d tx, %s", msg.BlockHash(),
|
||||
header.Version, len(msg.Transactions), header.Timestamp)
|
||||
|
||||
case *wire.MsgInv:
|
||||
return invSummary(msg.InvList)
|
||||
|
||||
case *wire.MsgNotFound:
|
||||
return invSummary(msg.InvList)
|
||||
|
||||
case *wire.MsgGetData:
|
||||
return invSummary(msg.InvList)
|
||||
|
||||
case *wire.MsgGetBlocks:
|
||||
return locatorSummary(msg.BlockLocatorHashes, &msg.HashStop)
|
||||
|
||||
case *wire.MsgGetHeaders:
|
||||
return locatorSummary(msg.BlockLocatorHashes, &msg.HashStop)
|
||||
|
||||
case *wire.MsgHeaders:
|
||||
return fmt.Sprintf("num %d", len(msg.Headers))
|
||||
|
||||
case *wire.MsgGetCFHeaders:
|
||||
return fmt.Sprintf("start_height=%d, stop_hash=%v",
|
||||
msg.StartHeight, msg.StopHash)
|
||||
|
||||
case *wire.MsgCFHeaders:
|
||||
return fmt.Sprintf("stop_hash=%v, num_filter_hashes=%d",
|
||||
msg.StopHash, len(msg.FilterHashes))
|
||||
|
||||
case *wire.MsgReject:
|
||||
// Ensure the variable length strings don't contain any
|
||||
// characters which are even remotely dangerous such as HTML
|
||||
// control characters, etc. Also limit them to sane length for
|
||||
// logging.
|
||||
rejCommand := sanitizeString(msg.Cmd, wire.CommandSize)
|
||||
rejReason := sanitizeString(msg.Reason, maxRejectReasonLen)
|
||||
summary := fmt.Sprintf("cmd %v, code %v, reason %v", rejCommand,
|
||||
msg.Code, rejReason)
|
||||
if rejCommand == wire.CmdBlock || rejCommand == wire.CmdTx {
|
||||
summary += fmt.Sprintf(", hash %v", msg.Hash)
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
// No summary for other messages.
|
||||
return ""
|
||||
}
|
||||
127
vendor/github.com/btcsuite/btcd/peer/mruinvmap.go
generated
vendored
Normal file
127
vendor/github.com/btcsuite/btcd/peer/mruinvmap.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
// 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 peer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// mruInventoryMap provides a concurrency safe map that is limited to a maximum
|
||||
// number of items with eviction for the oldest entry when the limit is
|
||||
// exceeded.
|
||||
type mruInventoryMap struct {
|
||||
invMtx sync.Mutex
|
||||
invMap map[wire.InvVect]*list.Element // nearly O(1) lookups
|
||||
invList *list.List // O(1) insert, update, delete
|
||||
limit uint
|
||||
}
|
||||
|
||||
// String returns the map as a human-readable string.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) String() string {
|
||||
m.invMtx.Lock()
|
||||
defer m.invMtx.Unlock()
|
||||
|
||||
lastEntryNum := len(m.invMap) - 1
|
||||
curEntry := 0
|
||||
buf := bytes.NewBufferString("[")
|
||||
for iv := range m.invMap {
|
||||
buf.WriteString(fmt.Sprintf("%v", iv))
|
||||
if curEntry < lastEntryNum {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
curEntry++
|
||||
}
|
||||
buf.WriteString("]")
|
||||
|
||||
return fmt.Sprintf("<%d>%s", m.limit, buf.String())
|
||||
}
|
||||
|
||||
// Exists returns whether or not the passed inventory item is in the map.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) Exists(iv *wire.InvVect) bool {
|
||||
m.invMtx.Lock()
|
||||
_, exists := m.invMap[*iv]
|
||||
m.invMtx.Unlock()
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
// Add adds the passed inventory to the map and handles eviction of the oldest
|
||||
// item if adding the new item would exceed the max limit. Adding an existing
|
||||
// item makes it the most recently used item.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) Add(iv *wire.InvVect) {
|
||||
m.invMtx.Lock()
|
||||
defer m.invMtx.Unlock()
|
||||
|
||||
// When the limit is zero, nothing can be added to the map, so just
|
||||
// return.
|
||||
if m.limit == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// When the entry already exists move it to the front of the list
|
||||
// thereby marking it most recently used.
|
||||
if node, exists := m.invMap[*iv]; exists {
|
||||
m.invList.MoveToFront(node)
|
||||
return
|
||||
}
|
||||
|
||||
// Evict the least recently used entry (back of the list) if the the new
|
||||
// entry would exceed the size limit for the map. Also reuse the list
|
||||
// node so a new one doesn't have to be allocated.
|
||||
if uint(len(m.invMap))+1 > m.limit {
|
||||
node := m.invList.Back()
|
||||
lru := node.Value.(*wire.InvVect)
|
||||
|
||||
// Evict least recently used item.
|
||||
delete(m.invMap, *lru)
|
||||
|
||||
// Reuse the list node of the item that was just evicted for the
|
||||
// new item.
|
||||
node.Value = iv
|
||||
m.invList.MoveToFront(node)
|
||||
m.invMap[*iv] = node
|
||||
return
|
||||
}
|
||||
|
||||
// The limit hasn't been reached yet, so just add the new item.
|
||||
node := m.invList.PushFront(iv)
|
||||
m.invMap[*iv] = node
|
||||
}
|
||||
|
||||
// Delete deletes the passed inventory item from the map (if it exists).
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) Delete(iv *wire.InvVect) {
|
||||
m.invMtx.Lock()
|
||||
if node, exists := m.invMap[*iv]; exists {
|
||||
m.invList.Remove(node)
|
||||
delete(m.invMap, *iv)
|
||||
}
|
||||
m.invMtx.Unlock()
|
||||
}
|
||||
|
||||
// newMruInventoryMap returns a new inventory map that is limited to the number
|
||||
// of entries specified by limit. When the number of entries exceeds the limit,
|
||||
// the oldest (least recently used) entry will be removed to make room for the
|
||||
// new entry.
|
||||
func newMruInventoryMap(limit uint) *mruInventoryMap {
|
||||
m := mruInventoryMap{
|
||||
invMap: make(map[wire.InvVect]*list.Element),
|
||||
invList: list.New(),
|
||||
limit: limit,
|
||||
}
|
||||
return &m
|
||||
}
|
||||
125
vendor/github.com/btcsuite/btcd/peer/mrunoncemap.go
generated
vendored
Normal file
125
vendor/github.com/btcsuite/btcd/peer/mrunoncemap.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package peer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// mruNonceMap provides a concurrency safe map that is limited to a maximum
|
||||
// number of items with eviction for the oldest entry when the limit is
|
||||
// exceeded.
|
||||
type mruNonceMap struct {
|
||||
mtx sync.Mutex
|
||||
nonceMap map[uint64]*list.Element // nearly O(1) lookups
|
||||
nonceList *list.List // O(1) insert, update, delete
|
||||
limit uint
|
||||
}
|
||||
|
||||
// String returns the map as a human-readable string.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) String() string {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
lastEntryNum := len(m.nonceMap) - 1
|
||||
curEntry := 0
|
||||
buf := bytes.NewBufferString("[")
|
||||
for nonce := range m.nonceMap {
|
||||
buf.WriteString(fmt.Sprintf("%d", nonce))
|
||||
if curEntry < lastEntryNum {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
curEntry++
|
||||
}
|
||||
buf.WriteString("]")
|
||||
|
||||
return fmt.Sprintf("<%d>%s", m.limit, buf.String())
|
||||
}
|
||||
|
||||
// Exists returns whether or not the passed nonce is in the map.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) Exists(nonce uint64) bool {
|
||||
m.mtx.Lock()
|
||||
_, exists := m.nonceMap[nonce]
|
||||
m.mtx.Unlock()
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
// Add adds the passed nonce to the map and handles eviction of the oldest item
|
||||
// if adding the new item would exceed the max limit. Adding an existing item
|
||||
// makes it the most recently used item.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) Add(nonce uint64) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
// When the limit is zero, nothing can be added to the map, so just
|
||||
// return.
|
||||
if m.limit == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// When the entry already exists move it to the front of the list
|
||||
// thereby marking it most recently used.
|
||||
if node, exists := m.nonceMap[nonce]; exists {
|
||||
m.nonceList.MoveToFront(node)
|
||||
return
|
||||
}
|
||||
|
||||
// Evict the least recently used entry (back of the list) if the the new
|
||||
// entry would exceed the size limit for the map. Also reuse the list
|
||||
// node so a new one doesn't have to be allocated.
|
||||
if uint(len(m.nonceMap))+1 > m.limit {
|
||||
node := m.nonceList.Back()
|
||||
lru := node.Value.(uint64)
|
||||
|
||||
// Evict least recently used item.
|
||||
delete(m.nonceMap, lru)
|
||||
|
||||
// Reuse the list node of the item that was just evicted for the
|
||||
// new item.
|
||||
node.Value = nonce
|
||||
m.nonceList.MoveToFront(node)
|
||||
m.nonceMap[nonce] = node
|
||||
return
|
||||
}
|
||||
|
||||
// The limit hasn't been reached yet, so just add the new item.
|
||||
node := m.nonceList.PushFront(nonce)
|
||||
m.nonceMap[nonce] = node
|
||||
}
|
||||
|
||||
// Delete deletes the passed nonce from the map (if it exists).
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) Delete(nonce uint64) {
|
||||
m.mtx.Lock()
|
||||
if node, exists := m.nonceMap[nonce]; exists {
|
||||
m.nonceList.Remove(node)
|
||||
delete(m.nonceMap, nonce)
|
||||
}
|
||||
m.mtx.Unlock()
|
||||
}
|
||||
|
||||
// newMruNonceMap returns a new nonce map that is limited to the number of
|
||||
// entries specified by limit. When the number of entries exceeds the limit,
|
||||
// the oldest (least recently used) entry will be removed to make room for the
|
||||
// new entry.
|
||||
func newMruNonceMap(limit uint) *mruNonceMap {
|
||||
m := mruNonceMap{
|
||||
nonceMap: make(map[uint64]*list.Element),
|
||||
nonceList: list.New(),
|
||||
limit: limit,
|
||||
}
|
||||
return &m
|
||||
}
|
||||
2280
vendor/github.com/btcsuite/btcd/peer/peer.go
generated
vendored
Normal file
2280
vendor/github.com/btcsuite/btcd/peer/peer.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user