swarm/chunk: move chunk related declarations to chunk package (#19170)
This commit is contained in:
committed by
Anton Evangelatov
parent
b7e0dec6bd
commit
f0233948d2
@ -1,5 +1,109 @@
|
||||
package chunk
|
||||
|
||||
const (
|
||||
DefaultSize = 4096
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultSize = 4096
|
||||
MaxPO = 16
|
||||
AddressLength = 32
|
||||
)
|
||||
|
||||
var (
|
||||
ErrChunkNotFound = errors.New("chunk not found")
|
||||
ErrChunkInvalid = errors.New("invalid chunk")
|
||||
)
|
||||
|
||||
type Chunk interface {
|
||||
Address() Address
|
||||
Data() []byte
|
||||
}
|
||||
|
||||
type chunk struct {
|
||||
addr Address
|
||||
sdata []byte
|
||||
}
|
||||
|
||||
func NewChunk(addr Address, data []byte) *chunk {
|
||||
return &chunk{
|
||||
addr: addr,
|
||||
sdata: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *chunk) Address() Address {
|
||||
return c.addr
|
||||
}
|
||||
|
||||
func (c *chunk) Data() []byte {
|
||||
return c.sdata
|
||||
}
|
||||
|
||||
func (self *chunk) String() string {
|
||||
return fmt.Sprintf("Address: %v Chunksize: %v", self.addr.Log(), len(self.sdata))
|
||||
}
|
||||
|
||||
type Address []byte
|
||||
|
||||
var ZeroAddr = Address(common.Hash{}.Bytes())
|
||||
|
||||
func (a Address) Hex() string {
|
||||
return fmt.Sprintf("%064x", []byte(a[:]))
|
||||
}
|
||||
|
||||
func (a Address) Log() string {
|
||||
if len(a[:]) < 8 {
|
||||
return fmt.Sprintf("%x", []byte(a[:]))
|
||||
}
|
||||
return fmt.Sprintf("%016x", []byte(a[:8]))
|
||||
}
|
||||
|
||||
func (a Address) String() string {
|
||||
return fmt.Sprintf("%064x", []byte(a))
|
||||
}
|
||||
|
||||
func (a Address) MarshalJSON() (out []byte, err error) {
|
||||
return []byte(`"` + a.String() + `"`), nil
|
||||
}
|
||||
|
||||
func (a *Address) UnmarshalJSON(value []byte) error {
|
||||
s := string(value)
|
||||
*a = make([]byte, 32)
|
||||
h := common.Hex2Bytes(s[1 : len(s)-1])
|
||||
copy(*a, h)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Proximity returns the proximity order of the MSB distance between x and y
|
||||
//
|
||||
// The distance metric MSB(x, y) of two equal length byte sequences x an y is the
|
||||
// value of the binary integer cast of the x^y, ie., x and y bitwise xor-ed.
|
||||
// the binary cast is big endian: most significant bit first (=MSB).
|
||||
//
|
||||
// Proximity(x, y) is a discrete logarithmic scaling of the MSB distance.
|
||||
// It is defined as the reverse rank of the integer part of the base 2
|
||||
// logarithm of the distance.
|
||||
// It is calculated by counting the number of common leading zeros in the (MSB)
|
||||
// binary representation of the x^y.
|
||||
//
|
||||
// (0 farthest, 255 closest, 256 self)
|
||||
func Proximity(one, other []byte) (ret int) {
|
||||
b := (MaxPO-1)/8 + 1
|
||||
if b > len(one) {
|
||||
b = len(one)
|
||||
}
|
||||
m := 8
|
||||
for i := 0; i < b; i++ {
|
||||
oxo := one[i] ^ other[i]
|
||||
for j := 0; j < m; j++ {
|
||||
if (oxo>>uint8(7-j))&0x01 != 0 {
|
||||
return i*8 + j
|
||||
}
|
||||
}
|
||||
}
|
||||
return MaxPO
|
||||
}
|
||||
|
186
swarm/chunk/proximity_test.go
Normal file
186
swarm/chunk/proximity_test.go
Normal file
@ -0,0 +1,186 @@
|
||||
// Copyright 2018 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package chunk
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestProximity validates Proximity function with explicit
|
||||
// values in a table-driven test. It is highly dependant on
|
||||
// MaxPO constant and it validates cases up to MaxPO=32.
|
||||
func TestProximity(t *testing.T) {
|
||||
// integer from base2 encoded string
|
||||
bx := func(s string) uint8 {
|
||||
i, err := strconv.ParseUint(s, 2, 8)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return uint8(i)
|
||||
}
|
||||
// adjust expected bins in respect to MaxPO
|
||||
limitPO := func(po uint8) uint8 {
|
||||
if po > MaxPO {
|
||||
return MaxPO
|
||||
}
|
||||
return po
|
||||
}
|
||||
base := []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00000000")}
|
||||
for _, tc := range []struct {
|
||||
addr []byte
|
||||
po uint8
|
||||
}{
|
||||
{
|
||||
addr: base,
|
||||
po: MaxPO,
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("10000000"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(0),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("01000000"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(1),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00100000"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(2),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00010000"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(3),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00001000"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(4),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000100"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(5),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000010"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(6),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000001"), bx("00000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(7),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("10000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(8),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("01000000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(9),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00100000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(10),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00010000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(11),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00001000"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(12),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000100"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(13),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000010"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(14),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000001"), bx("00000000"), bx("00000000")},
|
||||
po: limitPO(15),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("10000000"), bx("00000000")},
|
||||
po: limitPO(16),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("01000000"), bx("00000000")},
|
||||
po: limitPO(17),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00100000"), bx("00000000")},
|
||||
po: limitPO(18),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00010000"), bx("00000000")},
|
||||
po: limitPO(19),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00001000"), bx("00000000")},
|
||||
po: limitPO(20),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000100"), bx("00000000")},
|
||||
po: limitPO(21),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000010"), bx("00000000")},
|
||||
po: limitPO(22),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000001"), bx("00000000")},
|
||||
po: limitPO(23),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("10000000")},
|
||||
po: limitPO(24),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("01000000")},
|
||||
po: limitPO(25),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00100000")},
|
||||
po: limitPO(26),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00010000")},
|
||||
po: limitPO(27),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00001000")},
|
||||
po: limitPO(28),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00000100")},
|
||||
po: limitPO(29),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00000010")},
|
||||
po: limitPO(30),
|
||||
},
|
||||
{
|
||||
addr: []byte{bx("00000000"), bx("00000000"), bx("00000000"), bx("00000001")},
|
||||
po: limitPO(31),
|
||||
},
|
||||
} {
|
||||
got := uint8(Proximity(base, tc.addr))
|
||||
if got != tc.po {
|
||||
t.Errorf("got %v bin, want %v", got, tc.po)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user