addrmgr: Always use a 50% chance between tried and new entries.

This change was suggested as Countermeasure 2 in
Eclipse Attacks on Bitcoin's Peer-to-Peer Network, Ethan
Heilman, Alison Kendler, Aviv Zohar, Sharon Goldberg. ePrint Archive
Report 2015/263. March 2015.

This mimics Bitcoin Core commit c6a63ceeb4956933588995bcf01dc3095aaeb1fc
This commit is contained in:
David Hill 2015-04-06 12:13:00 -04:00
parent 320ecea6a0
commit 0eef96e1c8
3 changed files with 9 additions and 26 deletions

View file

@ -12,7 +12,6 @@ import (
"encoding/json"
"fmt"
"io"
"math"
"math/rand"
"net"
"os"
@ -741,7 +740,7 @@ func NetAddressKey(na *wire.NetAddress) string {
// random one from the possible addresses with preference given to ones that
// have not been used recently and should not pick 'close' addresses
// consecutively.
func (a *AddrManager) GetAddress(class string, newBias int) *KnownAddress {
func (a *AddrManager) GetAddress(class string) *KnownAddress {
// Protect concurrent access.
a.mtx.Lock()
defer a.mtx.Unlock()
@ -750,20 +749,8 @@ func (a *AddrManager) GetAddress(class string, newBias int) *KnownAddress {
return nil
}
if newBias > 100 {
newBias = 100
}
if newBias < 0 {
newBias = 0
}
// Bias between new and tried addresses.
triedCorrelation := math.Sqrt(float64(a.nTried)) *
(100.0 - float64(newBias))
newCorrelation := math.Sqrt(float64(a.nNew)) * float64(newBias)
if ((newCorrelation + triedCorrelation) * a.rand.Float64()) <
triedCorrelation {
// Use a 50% chance for choosing between tried and new table entries.
if a.nTried > 0 && (a.nNew == 0 || a.rand.Intn(2) == 0) {
// Tried entry.
large := 1 << 30
factor := 1.0

View file

@ -221,7 +221,7 @@ func TestAttempt(t *testing.T) {
if err != nil {
t.Fatalf("Adding address failed: %v", err)
}
ka := n.GetAddress("any", 100)
ka := n.GetAddress("any")
if !ka.LastAttempt().IsZero() {
t.Errorf("Address should not have attempts, but does")
@ -243,7 +243,7 @@ func TestConnected(t *testing.T) {
if err != nil {
t.Fatalf("Adding address failed: %v", err)
}
ka := n.GetAddress("any", 100)
ka := n.GetAddress("any")
na := ka.NetAddress()
na.Timestamp = time.Now().Add(time.Hour * -1) // make it an hour ago
@ -334,7 +334,7 @@ func TestGetAddress(t *testing.T) {
n := addrmgr.New("testgetaddress", lookupFunc)
// Get an address from an empty set (should error)
if rv := n.GetAddress("any", 10); rv != nil {
if rv := n.GetAddress("any"); rv != nil {
t.Errorf("GetAddress failed: got: %v want: %v\n", rv, nil)
}
@ -343,7 +343,7 @@ func TestGetAddress(t *testing.T) {
if err != nil {
t.Fatalf("Adding address failed: %v", err)
}
ka := n.GetAddress("any", 120) // 100 bias is max, but shouldn't error
ka := n.GetAddress("any")
if ka == nil {
t.Fatalf("Did not get an address where there is one in the pool")
}
@ -353,7 +353,7 @@ func TestGetAddress(t *testing.T) {
// Mark this as a good address and get it
n.Good(ka.NetAddress())
ka = n.GetAddress("any", -10) // 0 bias is min, but shouldn't error
ka = n.GetAddress("any")
if ka == nil {
t.Fatalf("Did not get an address where there is one in the pool")
}

View file

@ -695,15 +695,11 @@ out:
tries := 0
for state.NeedMoreOutbound() &&
atomic.LoadInt32(&s.shutdown) == 0 {
// We bias like bitcoind does, 10 for no outgoing
// up to 90 (8) for the selection of new vs tried
//addresses.
nPeers := state.OutboundCount()
if nPeers > 8 {
nPeers = 8
}
addr := s.addrManager.GetAddress("any", 10+nPeers*10)
addr := s.addrManager.GetAddress("any")
if addr == nil {
break
}