Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split go-ipfs/routing/kbucket into go-libp2p-kbucket #1

Merged
merged 78 commits into from
Aug 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
560a474
moved routing table code into its own package
whyrusleeping Aug 9, 2014
534dbca
tiered put/get implemented
whyrusleeping Aug 10, 2014
2f8828d
more work implementing coral type lookups
whyrusleeping Aug 11, 2014
9b28664
more tests and add in table filtering by peer latency
whyrusleeping Aug 12, 2014
8c87962
POut should not have a newline
jbenet Aug 17, 2014
5244bf9
Made the DHT module pass golint
cleichner Aug 17, 2014
751f985
Made routing code pass golint.
cleichner Aug 17, 2014
6aca2ab
fixing up some bitswap stuff after the PR
whyrusleeping Aug 28, 2014
7550fd1
moved keyspace
jbenet Sep 17, 2014
955487f
kbucket use new keyspace
jbenet Sep 17, 2014
a35399e
refactored keyspace Adjusted -> Bytes
jbenet Sep 17, 2014
c498a1d
refactored keyspace Adjusted -> Bytes
jbenet Sep 17, 2014
706732d
fixed keyspace tests on 32 bit systems
whyrusleeping Oct 4, 2014
aea8c8b
changed logging, in dht and elsewhere
jbenet Oct 8, 2014
1e9aa6d
add in some extra debug logging, and increase routing table latencies
whyrusleeping Oct 8, 2014
4935b4c
u.DOut -> log.Debug
jbenet Oct 9, 2014
346c167
moved XOR keyspace -> util
jbenet Oct 18, 2014
4cb779a
keyspace XOR naming
jbenet Oct 19, 2014
87a7984
peer.Peer is now an interface
jbenet Oct 20, 2014
564b0ac
fix for #141, routing table segmentation
whyrusleeping Oct 22, 2014
6344102
rewrite findpeer and other dht tweaks
whyrusleeping Oct 25, 2014
e50b5e7
go-vet friendly codebase
jbenet Oct 25, 2014
2cc6e0b
benchmark secure channel
whyrusleeping Oct 26, 2014
842efb9
write a few package doc strings to improve look of godoc
whyrusleeping Nov 8, 2014
140df99
peer change: peer.Peer -> peer.ID
jbenet Dec 19, 2014
8bdc248
dht bugfix: unlock on print
jbenet Dec 24, 2014
53d644e
routing table: better printing (see bkts)
jbenet Dec 24, 2014
af02bba
rewrite of provides to better select peers to send RPCs to
whyrusleeping Dec 14, 2014
e26510c
introducing p2p pkg
jbenet Dec 29, 2014
fde200d
crypto -> p2p/crypto
jbenet Dec 29, 2014
76b4cb5
routing/dht: adjust routing table on peer conn/disc
jbenet Jan 24, 2015
b819b92
dht/kbucket: race condition fix
jbenet Jan 24, 2015
f4dde7a
Merge pull request #640 from jbenet/races
jbenet Jan 24, 2015
c0f7104
dropped down log.Errors
jbenet Jan 27, 2015
b2a3efb
kbucket: fix data race
jbenet Feb 5, 2015
a1c198d
routing/kbucket: cleaner "public" interface for bucket
jbenet Feb 5, 2015
3f346ee
fixed dht kbucket race
jbenet Mar 4, 2015
ea04d1b
Reorged imports from jbenet/go-ipfs to ipfs/go-ipfs
hosh Mar 31, 2015
b0e10cb
Reorged imports from jbenet/go-ipfs to ipfs/go-ipfs
hosh Mar 31, 2015
191c1d3
Run 'gofmt -s -w' on these files
May 18, 2015
995989a
move util.Key into its own package under blocks
whyrusleeping Jun 1, 2015
31cda68
extract logging
whyrusleeping Sep 15, 2015
ef7bd25
replace imports with absolute path instead of using symlink
whyrusleeping Oct 1, 2015
59943a9
update code to use new logging changes
whyrusleeping Oct 27, 2015
5dfacc8
vendor logging lib update
whyrusleeping Oct 30, 2015
2fa2f79
if bucket doesnt have enough peers, grab more elsewhere
whyrusleeping Nov 13, 2015
ddb5ee6
initial vendoring of libp2p outside of the repo with gx
whyrusleeping Jan 27, 2016
e659727
go-keyspace dep from libp2p added
whyrusleeping Jan 28, 2016
d4c73fe
correct go-log dep
whyrusleeping Jan 28, 2016
3d1458c
update libp2p dep
whyrusleeping Jan 31, 2016
8ac6e9e
do that last thing again
whyrusleeping Jan 31, 2016
b7759d6
Use gx vendored go-ipfs-utils where possible
whyrusleeping Feb 9, 2016
86ad96b
Use gx vendored go-ipfs-utils where possible
whyrusleeping Feb 9, 2016
901bcb3
update libp2p dep
whyrusleeping Mar 9, 2016
bcde6c4
update utp and cleanup more godeps along the way
whyrusleeping Mar 30, 2016
f6916df
switch to new libp2p with mss crypto
whyrusleeping Apr 6, 2016
3466d43
update libp2p dep to fix hanging listeners problem
whyrusleeping Apr 11, 2016
5ef5c7c
Update go-libp2p
Apr 17, 2016
155efe2
Use extracted go-libp2p-crypto, -secio, -peer packages
Apr 17, 2016
9ce09df
Update go-log to 1.1.0 and fix calls to go-log.Uuid
hsanjuan May 4, 2016
1f80f59
update libp2p with go-multiaddr and go-stream-muxer updates
whyrusleeping May 10, 2016
9c04bb9
update go-libp2p 3.2.2, nil maddr fixes
whyrusleeping May 17, 2016
13a2c03
update libp2p to v3.3.1
whyrusleeping Jun 1, 2016
b26439a
Update go-log
Kubuxu Jun 9, 2016
0ee12a2
pull in libp2p updates with utp fixes
whyrusleeping Jun 11, 2016
b7641d6
a few small changes to make the dht more efficient
whyrusleeping Jun 12, 2016
9ad0b6c
sort peers outside of locks
whyrusleeping Jun 12, 2016
163ddd5
Update go-log in whole dependency tree (#2898)
Kubuxu Jun 24, 2016
9c00a96
Add docs
geoah Aug 25, 2016
138396b
Undo gx rewrites
geoah Aug 25, 2016
826baf2
Add travis-ci
geoah Aug 25, 2016
314c3cb
Add 'keyspace/' from commit '86ad96b45f5a4eef61a64e96269fa6af3e49d657'
geoah Aug 26, 2016
5add21a
Undo gx rewrites
geoah Aug 26, 2016
9055fe3
Fix docs
geoah Aug 26, 2016
6d2cddd
Fix ks package
geoah Aug 26, 2016
9968b7d
Use latest gx versions
geoah Aug 31, 2016
d401aca
Publish gx v1.0.0
geoah Aug 31, 2016
e8919b2
Move to go 1.7
geoah Aug 31, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gx/lastpubver
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.0: QmbS7NcH4KqZL71ZwzVZAt1CpVpAtUBaHXuDenjnXF78Wa
24 changes: 24 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
os:
- linux
- osx

language: go

go:
- 1.7

env:
- GO15VENDOREXPERIMENT=1

install: true

script:
- make deps
- go test ./...

cache:
directories:
- $GOPATH/src/gx

notifications:
email: false
12 changes: 6 additions & 6 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License
The MIT License (MIT)

Copyright (c) 2016 libp2p
Copyright (c) 2016 Protocol Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export IPFS_API ?= v04x.ipfs.io

gx:
go get -u github.com/whyrusleeping/gx
go get -u github.com/whyrusleeping/gx-go

deps: gx
gx --verbose install --global
gx-go rewrite
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
# go-libp2p-kbucket
A kbucket implementation for use as a routing table

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)

> A kbucket implementation for use as a routing table

## Documenation

See https://godoc.org/github.com/libp2p/go-libp2p-kbucket.

## Contribute

Feel free to join in. All welcome. Open an [issue](https://github.com/ipfs/go-key/issues)!

This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).

### Want to hack on IPFS?

[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md)

## License

MIT
108 changes: 108 additions & 0 deletions bucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package kbucket

import (
"container/list"
"sync"

peer "github.com/ipfs/go-libp2p-peer"
)

// Bucket holds a list of peers.
type Bucket struct {
lk sync.RWMutex
list *list.List
}

func newBucket() *Bucket {
b := new(Bucket)
b.list = list.New()
return b
}

func (b *Bucket) Peers() []peer.ID {
b.lk.RLock()
defer b.lk.RUnlock()
ps := make([]peer.ID, 0, b.list.Len())
for e := b.list.Front(); e != nil; e = e.Next() {
id := e.Value.(peer.ID)
ps = append(ps, id)
}
return ps
}

func (b *Bucket) Has(id peer.ID) bool {
b.lk.RLock()
defer b.lk.RUnlock()
for e := b.list.Front(); e != nil; e = e.Next() {
if e.Value.(peer.ID) == id {
return true
}
}
return false
}

func (b *Bucket) Remove(id peer.ID) {
b.lk.Lock()
defer b.lk.Unlock()
for e := b.list.Front(); e != nil; e = e.Next() {
if e.Value.(peer.ID) == id {
b.list.Remove(e)
}
}
}

func (b *Bucket) MoveToFront(id peer.ID) {
b.lk.Lock()
defer b.lk.Unlock()
for e := b.list.Front(); e != nil; e = e.Next() {
if e.Value.(peer.ID) == id {
b.list.MoveToFront(e)
}
}
}

func (b *Bucket) PushFront(p peer.ID) {
b.lk.Lock()
b.list.PushFront(p)
b.lk.Unlock()
}

func (b *Bucket) PopBack() peer.ID {
b.lk.Lock()
defer b.lk.Unlock()
last := b.list.Back()
b.list.Remove(last)
return last.Value.(peer.ID)
}

func (b *Bucket) Len() int {
b.lk.RLock()
defer b.lk.RUnlock()
return b.list.Len()
}

// Split splits a buckets peers into two buckets, the methods receiver will have
// peers with CPL equal to cpl, the returned bucket will have peers with CPL
// greater than cpl (returned bucket has closer peers)
func (b *Bucket) Split(cpl int, target ID) *Bucket {
b.lk.Lock()
defer b.lk.Unlock()

out := list.New()
newbuck := newBucket()
newbuck.list = out
e := b.list.Front()
for e != nil {
peerID := ConvertPeerID(e.Value.(peer.ID))
peerCPL := commonPrefixLen(peerID, target)
if peerCPL > cpl {
cur := e
out.PushBack(e.Value)
e = e.Next()
b.list.Remove(cur)
continue
}
e = e.Next()
}
return newbuck
}
97 changes: 97 additions & 0 deletions keyspace/keyspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package keyspace

import (
"sort"

"math/big"
)

// Key represents an identifier in a KeySpace. It holds a reference to the
// associated KeySpace, as well references to both the Original identifier,
// as well as the new, KeySpace Bytes one.
type Key struct {

// Space is the KeySpace this Key is related to.
Space KeySpace

// Original is the original value of the identifier
Original []byte

// Bytes is the new value of the identifier, in the KeySpace.
Bytes []byte
}

// Equal returns whether this key is equal to another.
func (k1 Key) Equal(k2 Key) bool {
if k1.Space != k2.Space {
panic("k1 and k2 not in same key space.")
}
return k1.Space.Equal(k1, k2)
}

// Less returns whether this key comes before another.
func (k1 Key) Less(k2 Key) bool {
if k1.Space != k2.Space {
panic("k1 and k2 not in same key space.")
}
return k1.Space.Less(k1, k2)
}

// Distance returns this key's distance to another
func (k1 Key) Distance(k2 Key) *big.Int {
if k1.Space != k2.Space {
panic("k1 and k2 not in same key space.")
}
return k1.Space.Distance(k1, k2)
}

// KeySpace is an object used to do math on identifiers. Each keyspace has its
// own properties and rules. See XorKeySpace.
type KeySpace interface {

// Key converts an identifier into a Key in this space.
Key([]byte) Key

// Equal returns whether keys are equal in this key space
Equal(Key, Key) bool

// Distance returns the distance metric in this key space
Distance(Key, Key) *big.Int

// Less returns whether the first key is smaller than the second.
Less(Key, Key) bool
}

// byDistanceToCenter is a type used to sort Keys by proximity to a center.
type byDistanceToCenter struct {
Center Key
Keys []Key
}

func (s byDistanceToCenter) Len() int {
return len(s.Keys)
}

func (s byDistanceToCenter) Swap(i, j int) {
s.Keys[i], s.Keys[j] = s.Keys[j], s.Keys[i]
}

func (s byDistanceToCenter) Less(i, j int) bool {
a := s.Center.Distance(s.Keys[i])
b := s.Center.Distance(s.Keys[j])
return a.Cmp(b) == -1
}

// SortByDistance takes a KeySpace, a center Key, and a list of Keys toSort.
// It returns a new list, where the Keys toSort have been sorted by their
// distance to the center Key.
func SortByDistance(sp KeySpace, center Key, toSort []Key) []Key {
toSortCopy := make([]Key, len(toSort))
copy(toSortCopy, toSort)
bdtc := &byDistanceToCenter{
Center: center,
Keys: toSortCopy, // copy
}
sort.Sort(bdtc)
return bdtc.Keys
}
67 changes: 67 additions & 0 deletions keyspace/xor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package keyspace

import (
"bytes"
"crypto/sha256"
"math/big"

u "github.com/ipfs/go-ipfs-util"
)

// XORKeySpace is a KeySpace which:
// - normalizes identifiers using a cryptographic hash (sha256)
// - measures distance by XORing keys together
var XORKeySpace = &xorKeySpace{}
var _ KeySpace = XORKeySpace // ensure it conforms

type xorKeySpace struct{}

// Key converts an identifier into a Key in this space.
func (s *xorKeySpace) Key(id []byte) Key {
hash := sha256.Sum256(id)
key := hash[:]
return Key{
Space: s,
Original: id,
Bytes: key,
}
}

// Equal returns whether keys are equal in this key space
func (s *xorKeySpace) Equal(k1, k2 Key) bool {
return bytes.Equal(k1.Bytes, k2.Bytes)
}

// Distance returns the distance metric in this key space
func (s *xorKeySpace) Distance(k1, k2 Key) *big.Int {
// XOR the keys
k3 := u.XOR(k1.Bytes, k2.Bytes)

// interpret it as an integer
dist := big.NewInt(0).SetBytes(k3)
return dist
}

// Less returns whether the first key is smaller than the second.
func (s *xorKeySpace) Less(k1, k2 Key) bool {
a := k1.Bytes
b := k2.Bytes
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return a[i] < b[i]
}
}
return true
}

// ZeroPrefixLen returns the number of consecutive zeroes in a byte slice.
func ZeroPrefixLen(id []byte) int {
for i := 0; i < len(id); i++ {
for j := 0; j < 8; j++ {
if (id[i]>>uint8(7-j))&0x1 != 0 {
return i*8 + j
}
}
}
return len(id) * 8
}