diff --git a/go.mod b/go.mod index 15c261ce..80a3d765 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 github.com/btcsuite/winsvc v1.0.0 github.com/davecgh/go-spew v1.1.1 + github.com/decred/dcrd/lru v1.0.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 diff --git a/go.sum b/go.sum index 1ead212f..392d70f1 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= diff --git a/netsync/manager.go b/netsync/manager.go index 32715b8e..51c2cbe4 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -147,6 +147,25 @@ type peerSyncState struct { requestedBlocks map[chainhash.Hash]struct{} } +// limitAdd is a helper function for maps that require a maximum limit by +// evicting a random value if adding the new value would cause it to +// overflow the maximum allowed. +func limitAdd(m map[chainhash.Hash]struct{}, hash chainhash.Hash, limit int) { + if len(m)+1 > limit { + // Remove a random entry from the map. For most compilers, Go's + // range statement iterates starting at a random item although + // that is not 100% guaranteed by the spec. The iteration order + // is not important here because an adversary would have to be + // able to pull off preimage attacks on the hashing function in + // order to target eviction of specific entries anyways. + for txHash := range m { + delete(m, txHash) + break + } + } + m[hash] = struct{}{} +} + // SyncManager is used to communicate block related messages with peers. The // SyncManager is started as by executing Start() in a goroutine. Once started, // it selects peers to sync from and starts the initial block download. Once the @@ -579,8 +598,7 @@ func (sm *SyncManager) handleTxMsg(tmsg *txMsg) { if err != nil { // Do not request this transaction again until a new block // has been processed. - sm.rejectedTxns[*txHash] = struct{}{} - sm.limitMap(sm.rejectedTxns, maxRejectedTxns) + limitAdd(sm.rejectedTxns, *txHash, maxRejectedTxns) // When the error is a rule error, it means the transaction was // simply rejected as opposed to something actually going wrong, @@ -1202,9 +1220,8 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) { // Request the block if there is not already a pending // request. if _, exists := sm.requestedBlocks[iv.Hash]; !exists { - sm.requestedBlocks[iv.Hash] = struct{}{} - sm.limitMap(sm.requestedBlocks, maxRequestedBlocks) - state.requestedBlocks[iv.Hash] = struct{}{} + limitAdd(sm.requestedBlocks, iv.Hash, maxRequestedBlocks) + limitAdd(state.requestedBlocks, iv.Hash, maxRequestedBlocks) if peer.IsWitnessEnabled() { iv.Type = wire.InvTypeWitnessBlock @@ -1220,9 +1237,8 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) { // Request the transaction if there is not already a // pending request. if _, exists := sm.requestedTxns[iv.Hash]; !exists { - sm.requestedTxns[iv.Hash] = struct{}{} - sm.limitMap(sm.requestedTxns, maxRequestedTxns) - state.requestedTxns[iv.Hash] = struct{}{} + limitAdd(sm.requestedTxns, iv.Hash, maxRequestedTxns) + limitAdd(state.requestedTxns, iv.Hash, maxRequestedTxns) // If the peer is capable, request the txn // including all witness data. @@ -1245,24 +1261,6 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) { } } -// limitMap is a helper function for maps that require a maximum limit by -// evicting a random transaction if adding a new value would cause it to -// overflow the maximum allowed. -func (sm *SyncManager) limitMap(m map[chainhash.Hash]struct{}, limit int) { - if len(m)+1 > limit { - // Remove a random entry from the map. For most compilers, Go's - // range statement iterates starting at a random item although - // that is not 100% guaranteed by the spec. The iteration order - // is not important here because an adversary would have to be - // able to pull off preimage attacks on the hashing function in - // order to target eviction of specific entries anyways. - for txHash := range m { - delete(m, txHash) - return - } - } -} - // blockHandler is the main handler for the sync manager. It must be run as a // goroutine. It processes block and inv messages in a separate goroutine // from the peer handlers so the block (MsgBlock) messages are handled by a diff --git a/peer/mruinvmap.go b/peer/mruinvmap.go deleted file mode 100644 index 0bf1b2b3..00000000 --- a/peer/mruinvmap.go +++ /dev/null @@ -1,127 +0,0 @@ -// 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 -} diff --git a/peer/mruinvmap_test.go b/peer/mruinvmap_test.go deleted file mode 100644 index e5574601..00000000 --- a/peer/mruinvmap_test.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2013-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 ( - "crypto/rand" - "fmt" - "testing" - - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" -) - -// TestMruInventoryMap ensures the MruInventoryMap behaves as expected including -// limiting, eviction of least-recently used entries, specific entry removal, -// and existence tests. -func TestMruInventoryMap(t *testing.T) { - // Create a bunch of fake inventory vectors to use in testing the mru - // inventory code. - numInvVects := 10 - invVects := make([]*wire.InvVect, 0, numInvVects) - for i := 0; i < numInvVects; i++ { - hash := &chainhash.Hash{byte(i)} - iv := wire.NewInvVect(wire.InvTypeBlock, hash) - invVects = append(invVects, iv) - } - - tests := []struct { - name string - limit int - }{ - {name: "limit 0", limit: 0}, - {name: "limit 1", limit: 1}, - {name: "limit 5", limit: 5}, - {name: "limit 7", limit: 7}, - {name: "limit one less than available", limit: numInvVects - 1}, - {name: "limit all available", limit: numInvVects}, - } - -testLoop: - for i, test := range tests { - // Create a new mru inventory map limited by the specified test - // limit and add all of the test inventory vectors. This will - // cause evicition since there are more test inventory vectors - // than the limits. - mruInvMap := newMruInventoryMap(uint(test.limit)) - for j := 0; j < numInvVects; j++ { - mruInvMap.Add(invVects[j]) - } - - // Ensure the limited number of most recent entries in the - // inventory vector list exist. - for j := numInvVects - test.limit; j < numInvVects; j++ { - if !mruInvMap.Exists(invVects[j]) { - t.Errorf("Exists #%d (%s) entry %s does not "+ - "exist", i, test.name, *invVects[j]) - continue testLoop - } - } - - // Ensure the entries before the limited number of most recent - // entries in the inventory vector list do not exist. - for j := 0; j < numInvVects-test.limit; j++ { - if mruInvMap.Exists(invVects[j]) { - t.Errorf("Exists #%d (%s) entry %s exists", i, - test.name, *invVects[j]) - continue testLoop - } - } - - // Readd the entry that should currently be the least-recently - // used entry so it becomes the most-recently used entry, then - // force an eviction by adding an entry that doesn't exist and - // ensure the evicted entry is the new least-recently used - // entry. - // - // This check needs at least 2 entries. - if test.limit > 1 { - origLruIndex := numInvVects - test.limit - mruInvMap.Add(invVects[origLruIndex]) - - iv := wire.NewInvVect(wire.InvTypeBlock, - &chainhash.Hash{0x00, 0x01}) - mruInvMap.Add(iv) - - // Ensure the original lru entry still exists since it - // was updated and should've have become the mru entry. - if !mruInvMap.Exists(invVects[origLruIndex]) { - t.Errorf("MRU #%d (%s) entry %s does not exist", - i, test.name, *invVects[origLruIndex]) - continue testLoop - } - - // Ensure the entry that should've become the new lru - // entry was evicted. - newLruIndex := origLruIndex + 1 - if mruInvMap.Exists(invVects[newLruIndex]) { - t.Errorf("MRU #%d (%s) entry %s exists", i, - test.name, *invVects[newLruIndex]) - continue testLoop - } - } - - // Delete all of the entries in the inventory vector list, - // including those that don't exist in the map, and ensure they - // no longer exist. - for j := 0; j < numInvVects; j++ { - mruInvMap.Delete(invVects[j]) - if mruInvMap.Exists(invVects[j]) { - t.Errorf("Delete #%d (%s) entry %s exists", i, - test.name, *invVects[j]) - continue testLoop - } - } - } -} - -// TestMruInventoryMapStringer tests the stringized output for the -// MruInventoryMap type. -func TestMruInventoryMapStringer(t *testing.T) { - // Create a couple of fake inventory vectors to use in testing the mru - // inventory stringer code. - hash1 := &chainhash.Hash{0x01} - hash2 := &chainhash.Hash{0x02} - iv1 := wire.NewInvVect(wire.InvTypeBlock, hash1) - iv2 := wire.NewInvVect(wire.InvTypeBlock, hash2) - - // Create new mru inventory map and add the inventory vectors. - mruInvMap := newMruInventoryMap(uint(2)) - mruInvMap.Add(iv1) - mruInvMap.Add(iv2) - - // Ensure the stringer gives the expected result. Since map iteration - // is not ordered, either entry could be first, so account for both - // cases. - wantStr1 := fmt.Sprintf("<%d>[%s, %s]", 2, *iv1, *iv2) - wantStr2 := fmt.Sprintf("<%d>[%s, %s]", 2, *iv2, *iv1) - gotStr := mruInvMap.String() - if gotStr != wantStr1 && gotStr != wantStr2 { - t.Fatalf("unexpected string representation - got %q, want %q "+ - "or %q", gotStr, wantStr1, wantStr2) - } -} - -// BenchmarkMruInventoryList performs basic benchmarks on the most recently -// used inventory handling. -func BenchmarkMruInventoryList(b *testing.B) { - // Create a bunch of fake inventory vectors to use in benchmarking - // the mru inventory code. - b.StopTimer() - numInvVects := 100000 - invVects := make([]*wire.InvVect, 0, numInvVects) - for i := 0; i < numInvVects; i++ { - hashBytes := make([]byte, chainhash.HashSize) - rand.Read(hashBytes) - hash, _ := chainhash.NewHash(hashBytes) - iv := wire.NewInvVect(wire.InvTypeBlock, hash) - invVects = append(invVects, iv) - } - b.StartTimer() - - // Benchmark the add plus evicition code. - limit := 20000 - mruInvMap := newMruInventoryMap(uint(limit)) - for i := 0; i < b.N; i++ { - mruInvMap.Add(invVects[i%numInvVects]) - } -} diff --git a/peer/mrunoncemap.go b/peer/mrunoncemap.go deleted file mode 100644 index 5f7c7984..00000000 --- a/peer/mrunoncemap.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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 -} diff --git a/peer/mrunoncemap_test.go b/peer/mrunoncemap_test.go deleted file mode 100644 index bd7fb108..00000000 --- a/peer/mrunoncemap_test.go +++ /dev/null @@ -1,152 +0,0 @@ -// 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 ( - "fmt" - "testing" -) - -// TestMruNonceMap ensures the mruNonceMap behaves as expected including -// limiting, eviction of least-recently used entries, specific entry removal, -// and existence tests. -func TestMruNonceMap(t *testing.T) { - // Create a bunch of fake nonces to use in testing the mru nonce code. - numNonces := 10 - nonces := make([]uint64, 0, numNonces) - for i := 0; i < numNonces; i++ { - nonces = append(nonces, uint64(i)) - } - - tests := []struct { - name string - limit int - }{ - {name: "limit 0", limit: 0}, - {name: "limit 1", limit: 1}, - {name: "limit 5", limit: 5}, - {name: "limit 7", limit: 7}, - {name: "limit one less than available", limit: numNonces - 1}, - {name: "limit all available", limit: numNonces}, - } - -testLoop: - for i, test := range tests { - // Create a new mru nonce map limited by the specified test - // limit and add all of the test nonces. This will cause - // evicition since there are more test nonces than the limits. - mruNonceMap := newMruNonceMap(uint(test.limit)) - for j := 0; j < numNonces; j++ { - mruNonceMap.Add(nonces[j]) - } - - // Ensure the limited number of most recent entries in the list - // exist. - for j := numNonces - test.limit; j < numNonces; j++ { - if !mruNonceMap.Exists(nonces[j]) { - t.Errorf("Exists #%d (%s) entry %d does not "+ - "exist", i, test.name, nonces[j]) - continue testLoop - } - } - - // Ensure the entries before the limited number of most recent - // entries in the list do not exist. - for j := 0; j < numNonces-test.limit; j++ { - if mruNonceMap.Exists(nonces[j]) { - t.Errorf("Exists #%d (%s) entry %d exists", i, - test.name, nonces[j]) - continue testLoop - } - } - - // Readd the entry that should currently be the least-recently - // used entry so it becomes the most-recently used entry, then - // force an eviction by adding an entry that doesn't exist and - // ensure the evicted entry is the new least-recently used - // entry. - // - // This check needs at least 2 entries. - if test.limit > 1 { - origLruIndex := numNonces - test.limit - mruNonceMap.Add(nonces[origLruIndex]) - - mruNonceMap.Add(uint64(numNonces) + 1) - - // Ensure the original lru entry still exists since it - // was updated and should've have become the mru entry. - if !mruNonceMap.Exists(nonces[origLruIndex]) { - t.Errorf("MRU #%d (%s) entry %d does not exist", - i, test.name, nonces[origLruIndex]) - continue testLoop - } - - // Ensure the entry that should've become the new lru - // entry was evicted. - newLruIndex := origLruIndex + 1 - if mruNonceMap.Exists(nonces[newLruIndex]) { - t.Errorf("MRU #%d (%s) entry %d exists", i, - test.name, nonces[newLruIndex]) - continue testLoop - } - } - - // Delete all of the entries in the list, including those that - // don't exist in the map, and ensure they no longer exist. - for j := 0; j < numNonces; j++ { - mruNonceMap.Delete(nonces[j]) - if mruNonceMap.Exists(nonces[j]) { - t.Errorf("Delete #%d (%s) entry %d exists", i, - test.name, nonces[j]) - continue testLoop - } - } - } -} - -// TestMruNonceMapStringer tests the stringized output for the mruNonceMap type. -func TestMruNonceMapStringer(t *testing.T) { - // Create a couple of fake nonces to use in testing the mru nonce - // stringer code. - nonce1 := uint64(10) - nonce2 := uint64(20) - - // Create new mru nonce map and add the nonces. - mruNonceMap := newMruNonceMap(uint(2)) - mruNonceMap.Add(nonce1) - mruNonceMap.Add(nonce2) - - // Ensure the stringer gives the expected result. Since map iteration - // is not ordered, either entry could be first, so account for both - // cases. - wantStr1 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce1, nonce2) - wantStr2 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce2, nonce1) - gotStr := mruNonceMap.String() - if gotStr != wantStr1 && gotStr != wantStr2 { - t.Fatalf("unexpected string representation - got %q, want %q "+ - "or %q", gotStr, wantStr1, wantStr2) - } -} - -// BenchmarkMruNonceList performs basic benchmarks on the most recently used -// nonce handling. -func BenchmarkMruNonceList(b *testing.B) { - // Create a bunch of fake nonces to use in benchmarking the mru nonce - // code. - b.StopTimer() - numNonces := 100000 - nonces := make([]uint64, 0, numNonces) - for i := 0; i < numNonces; i++ { - nonces = append(nonces, uint64(i)) - } - b.StartTimer() - - // Benchmark the add plus evicition code. - limit := 20000 - mruNonceMap := newMruNonceMap(uint(limit)) - for i := 0; i < b.N; i++ { - mruNonceMap.Add(nonces[i%numNonces]) - } -} diff --git a/peer/peer.go b/peer/peer.go index 200acb32..82010f3b 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -24,6 +24,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/go-socks/socks" "github.com/davecgh/go-spew/spew" + "github.com/decred/dcrd/lru" ) const ( @@ -82,7 +83,7 @@ var ( // sentNonces houses the unique nonces that are generated when pushing // version messages that are used to detect self connections. - sentNonces = newMruNonceMap(50) + sentNonces = lru.NewCache(50) // allowSelfConns is only used to allow the tests to bypass the self // connection detecting and disconnect logic since they intentionally @@ -450,7 +451,7 @@ type Peer struct { wireEncoding wire.MessageEncoding - knownInventory *mruInventoryMap + knownInventory lru.Cache prevGetBlocksMtx sync.Mutex prevGetBlocksBegin *chainhash.Hash prevGetBlocksStop *chainhash.Hash @@ -1626,7 +1627,7 @@ out: // Don't send inventory that became known after // the initial check. - if p.knownInventory.Exists(iv) { + if p.knownInventory.Contains(iv) { continue } @@ -1832,7 +1833,7 @@ func (p *Peer) QueueMessageWithEncoding(msg wire.Message, doneChan chan<- struct func (p *Peer) QueueInventory(invVect *wire.InvVect) { // Don't add the inventory to the send queue if the peer is already // known to have it. - if p.knownInventory.Exists(invVect) { + if p.knownInventory.Contains(invVect) { return } @@ -1891,7 +1892,7 @@ func (p *Peer) readRemoteVersionMsg() error { } // Detect self connections. - if !allowSelfConns && sentNonces.Exists(msg.Nonce) { + if !allowSelfConns && sentNonces.Contains(msg.Nonce) { return errors.New("disconnecting peer connected to self") } @@ -2224,7 +2225,7 @@ func newPeerBase(origCfg *Config, inbound bool) *Peer { p := Peer{ inbound: inbound, wireEncoding: wire.BaseEncoding, - knownInventory: newMruInventoryMap(maxKnownInventory), + knownInventory: lru.NewCache(maxKnownInventory), stallControl: make(chan stallControlMsg, 1), // nonblocking sync outputQueue: make(chan outMsg, outputBufferSize), sendQueue: make(chan outMsg, 1), // nonblocking sync