From c9a20463e33d723f2493e83423d5dafa3441e4de Mon Sep 17 00:00:00 2001 From: nolash Date: Tue, 2 Jul 2019 15:37:53 +0200 Subject: [PATCH 1/5] network/bitvector: Multibit set/unset + string rep --- network/bitvector/bitvector.go | 38 +++++++++++++++++++++++++++++ network/bitvector/bitvector_test.go | 31 +++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/network/bitvector/bitvector.go b/network/bitvector/bitvector.go index 9583285023..c83147f6c6 100644 --- a/network/bitvector/bitvector.go +++ b/network/bitvector/bitvector.go @@ -57,6 +57,44 @@ func (bv *BitVector) Set(i int, v bool) { } } +func (bv *BitVector) SetBytes(bs []byte) error { + if len(bs) != bv.len { + return errors.New("invalid length") + } + for i := 0; i < bv.len*8; i++ { + bi := i / 8 + if bs[bi]&(0x01< 0 { + bv.Set(i, true) + } + } + return nil +} + +func (bv *BitVector) UnsetBytes(bs []byte) error { + if len(bs) != bv.len { + return errors.New("invalid length") + } + for i := 0; i < bv.len*8; i++ { + bi := i / 8 + if bs[bi]&(0x01< 0 { + bv.Set(i, false) + } + } + return nil +} + +// String implements Stringer interface +func (bv *BitVector) String() (s string) { + for i := 0; i < bv.len*8; i++ { + if bv.Get(i) { + s += "1" + } else { + s += "0" + } + } + return s +} + func (bv *BitVector) Bytes() []byte { return bv.b } diff --git a/network/bitvector/bitvector_test.go b/network/bitvector/bitvector_test.go index 4e62600389..2555bf86c5 100644 --- a/network/bitvector/bitvector_test.go +++ b/network/bitvector/bitvector_test.go @@ -102,3 +102,34 @@ func TestBitvectorNewFromBytesGet(t *testing.T) { t.Fatalf("element 3 is not set to true: state %08b", bv.b[0]) } } + +func TestBitVectorString(t *testing.T) { + b := []byte{0xa5, 0x81} + expect := "1010010110000001" + bv, err := NewFromBytes(b, 2) + if err != nil { + t.Fatal(err) + } + if bv.String() != expect { + t.Fatalf("bitvector string fail: got %s, expect %s", bv.String(), expect) + } +} + +func TestBitVectorSetUnsetBytes(t *testing.T) { + b := []byte{0xff, 0xff} + cb := []byte{0xa5, 0x81} + expectUnset := "0101101001111110" + expectReset := "1111111111111111" + bv, err := NewFromBytes(b, 2) + if err != nil { + t.Fatal(err) + } + bv.UnsetBytes(cb) + if bv.String() != expectUnset { + t.Fatalf("bitvector unset bytes fail: got %s, expect %s", bv.String(), expectUnset) + } + bv.SetBytes(cb) + if bv.String() != expectReset { + t.Fatalf("bitvector reset bytes fail: got %s, expect %s", bv.String(), expectReset) + } +} From e82555ef1c3a053048395eefdfd2cceea79ec662 Mon Sep 17 00:00:00 2001 From: nolash Date: Tue, 2 Jul 2019 15:46:17 +0200 Subject: [PATCH 2/5] network/bitvector: Add code comments --- network/bitvector/bitvector.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/network/bitvector/bitvector.go b/network/bitvector/bitvector.go index c83147f6c6..cb667c0c47 100644 --- a/network/bitvector/bitvector.go +++ b/network/bitvector/bitvector.go @@ -22,15 +22,20 @@ import ( var errInvalidLength = errors.New("invalid length") +// BitVector is a convenience object for manipulating and representing bit vectors type BitVector struct { len int b []byte } +// New creates a new bit vector with the given length func New(l int) (bv *BitVector, err error) { return NewFromBytes(make([]byte, l/8+1), l) } +// NewFromBytes creates a bit vector from the passed byte slice. +// +// Leftmost bit in byte slice becomes leftmost bit in bit vector func NewFromBytes(b []byte, l int) (bv *BitVector, err error) { if l <= 0 { return nil, errInvalidLength @@ -44,11 +49,13 @@ func NewFromBytes(b []byte, l int) (bv *BitVector, err error) { }, nil } +// Get gets the corresponding bit, counted from left to right func (bv *BitVector) Get(i int) bool { bi := i / 8 return bv.b[bi]&(0x1< Date: Tue, 2 Jul 2019 15:51:16 +0200 Subject: [PATCH 3/5] network/bitvector: Make Unset -> Set with bool false --- network/bitvector/bitvector.go | 23 +++++------------------ network/bitvector/bitvector_test.go | 11 ++++++++--- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/network/bitvector/bitvector.go b/network/bitvector/bitvector.go index cb667c0c47..90ac1db4a4 100644 --- a/network/bitvector/bitvector.go +++ b/network/bitvector/bitvector.go @@ -64,33 +64,20 @@ func (bv *BitVector) Set(i int, v bool) { } } -// SetBytes sets all bits in the bitvector that are set in the argument +// SetBytes modifies all bits in the bitvector that are set in the argument // -// The argument must be the same as the bitvector length -func (bv *BitVector) SetBytes(bs []byte) error { - if len(bs) != bv.len { - return errors.New("invalid length") - } - for i := 0; i < bv.len*8; i++ { - bi := i / 8 - if bs[bi]&(0x01< 0 { - bv.Set(i, true) - } - } - return nil -} - -// UnsetBytes UNSETS all bits in the bitvector that are set in the argument +// If v is true, it sets all bits in the bitvector that are set in the argument +// If v is false, it unsets all bites in the bitvector that are set in the argument // // The argument must be the same as the bitvector length -func (bv *BitVector) UnsetBytes(bs []byte) error { +func (bv *BitVector) SetBytes(bs []byte, v bool) error { if len(bs) != bv.len { return errors.New("invalid length") } for i := 0; i < bv.len*8; i++ { bi := i / 8 if bs[bi]&(0x01< 0 { - bv.Set(i, false) + bv.Set(i, v) } } return nil diff --git a/network/bitvector/bitvector_test.go b/network/bitvector/bitvector_test.go index 2555bf86c5..1eb454d8b7 100644 --- a/network/bitvector/bitvector_test.go +++ b/network/bitvector/bitvector_test.go @@ -18,6 +18,7 @@ package bitvector import "testing" +// TestBitvectorNew checks that enforcements of argument length works in the constructors func TestBitvectorNew(t *testing.T) { _, err := New(0) if err != errInvalidLength { @@ -40,6 +41,7 @@ func TestBitvectorNew(t *testing.T) { } } +// TestBitvectorGetSet tests correctness of individual Set and Get commands func TestBitvectorGetSet(t *testing.T) { for _, length := range []int{ 1, @@ -93,6 +95,7 @@ func TestBitvectorGetSet(t *testing.T) { } } +// TestBitvectorNewFromBytesGet tests that bit vector is initialized correctly from underlying byte slice func TestBitvectorNewFromBytesGet(t *testing.T) { bv, err := NewFromBytes([]byte{8}, 8) if err != nil { @@ -103,6 +106,7 @@ func TestBitvectorNewFromBytesGet(t *testing.T) { } } +// TestBitVectorString tests that string representation of bit vector is correct func TestBitVectorString(t *testing.T) { b := []byte{0xa5, 0x81} expect := "1010010110000001" @@ -115,7 +119,8 @@ func TestBitVectorString(t *testing.T) { } } -func TestBitVectorSetUnsetBytes(t *testing.T) { +// TestBitVectorSetUnsetBytes tests that setting and unsetting by byte slice modifies the bit vector correctly +func TestBitVectorSetBytes(t *testing.T) { b := []byte{0xff, 0xff} cb := []byte{0xa5, 0x81} expectUnset := "0101101001111110" @@ -124,11 +129,11 @@ func TestBitVectorSetUnsetBytes(t *testing.T) { if err != nil { t.Fatal(err) } - bv.UnsetBytes(cb) + bv.SetBytes(cb, false) if bv.String() != expectUnset { t.Fatalf("bitvector unset bytes fail: got %s, expect %s", bv.String(), expectUnset) } - bv.SetBytes(cb) + bv.SetBytes(cb, true) if bv.String() != expectReset { t.Fatalf("bitvector reset bytes fail: got %s, expect %s", bv.String(), expectReset) } From 8ea0af686928f2d32342eb10daff8154cd4bfc2f Mon Sep 17 00:00:00 2001 From: nolash Date: Tue, 2 Jul 2019 16:45:12 +0200 Subject: [PATCH 4/5] network/bitvector: Revert to Set/Unset --- network/bitvector/bitvector.go | 37 +++++++++++++++++++++++------ network/bitvector/bitvector_test.go | 8 +++---- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/network/bitvector/bitvector.go b/network/bitvector/bitvector.go index 90ac1db4a4..9473537140 100644 --- a/network/bitvector/bitvector.go +++ b/network/bitvector/bitvector.go @@ -55,8 +55,8 @@ func (bv *BitVector) Get(i int) bool { return bv.b[bi]&(0x1< 0 { + bv.set(i, true) + } + } + return nil +} + +// UnsetBytes UNSETS all bits in the bitvector that are set in the argument // // The argument must be the same as the bitvector length -func (bv *BitVector) SetBytes(bs []byte, v bool) error { +func (bv *BitVector) UnsetBytes(bs []byte) error { if len(bs) != bv.len { return errors.New("invalid length") } for i := 0; i < bv.len*8; i++ { bi := i / 8 if bs[bi]&(0x01< 0 { - bv.Set(i, v) + bv.set(i, false) } } return nil diff --git a/network/bitvector/bitvector_test.go b/network/bitvector/bitvector_test.go index 1eb454d8b7..9922af0b61 100644 --- a/network/bitvector/bitvector_test.go +++ b/network/bitvector/bitvector_test.go @@ -73,7 +73,7 @@ func TestBitvectorGetSet(t *testing.T) { }() for i := 0; i < length; i++ { - bv.Set(i, true) + bv.Set(i) for j := 0; j < length; j++ { if j == i { if !bv.Get(j) { @@ -86,7 +86,7 @@ func TestBitvectorGetSet(t *testing.T) { } } - bv.Set(i, false) + bv.Unset(i) if bv.Get(i) { t.Errorf("element on index %v is not set to false", i) @@ -129,11 +129,11 @@ func TestBitVectorSetBytes(t *testing.T) { if err != nil { t.Fatal(err) } - bv.SetBytes(cb, false) + bv.UnsetBytes(cb) if bv.String() != expectUnset { t.Fatalf("bitvector unset bytes fail: got %s, expect %s", bv.String(), expectUnset) } - bv.SetBytes(cb, true) + bv.SetBytes(cb) if bv.String() != expectReset { t.Fatalf("bitvector reset bytes fail: got %s, expect %s", bv.String(), expectReset) } From 786e0c317f32c7eb5cc3681f7b06396dff1e97ba Mon Sep 17 00:00:00 2001 From: nolash Date: Tue, 2 Jul 2019 16:50:07 +0200 Subject: [PATCH 5/5] network/stream: Update to new bitvector signature --- network/stream/messages.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/stream/messages.go b/network/stream/messages.go index 33320db289..8332785f43 100644 --- a/network/stream/messages.go +++ b/network/stream/messages.go @@ -231,7 +231,7 @@ func (p *Peer) handleOfferedHashesMsg(ctx context.Context, req *OfferedHashesMsg ctr++ // set the bit, so create a request - want.Set(i/HashSize, true) + want.Set(i / HashSize) log.Trace("need data", "ref", fmt.Sprintf("%x", hash), "request", true) // measure how long it takes before we mark chunks for retrieval, and actually send the request