package chunk 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 }