github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/swarm/network/kademlia/address.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package kademlia 13 14 import ( 15 "fmt" 16 "math/rand" 17 "strings" 18 19 "github.com/Sberex/go-sberex/common" 20 ) 21 22 type Address common.Hash 23 24 func (a Address) String() string { 25 return fmt.Sprintf("%x", a[:]) 26 } 27 28 func (a *Address) MarshalJSON() (out []byte, err error) { 29 return []byte(`"` + a.String() + `"`), nil 30 } 31 32 func (a *Address) UnmarshalJSON(value []byte) error { 33 *a = Address(common.HexToHash(string(value[1 : len(value)-1]))) 34 return nil 35 } 36 37 // the string form of the binary representation of an address (only first 8 bits) 38 func (a Address) Bin() string { 39 var bs []string 40 for _, b := range a[:] { 41 bs = append(bs, fmt.Sprintf("%08b", b)) 42 } 43 return strings.Join(bs, "") 44 } 45 46 /* 47 Proximity(x, y) returns the proximity order of the MSB distance between x and y 48 49 The distance metric MSB(x, y) of two equal length byte sequences x an y is the 50 value of the binary integer cast of the x^y, ie., x and y bitwise xor-ed. 51 the binary cast is big endian: most significant bit first (=MSB). 52 53 Proximity(x, y) is a discrete logarithmic scaling of the MSB distance. 54 It is defined as the reverse rank of the integer part of the base 2 55 logarithm of the distance. 56 It is calculated by counting the number of common leading zeros in the (MSB) 57 binary representation of the x^y. 58 59 (0 farthest, 255 closest, 256 self) 60 */ 61 func proximity(one, other Address) (ret int) { 62 for i := 0; i < len(one); i++ { 63 oxo := one[i] ^ other[i] 64 for j := 0; j < 8; j++ { 65 if (oxo>>uint8(7-j))&0x01 != 0 { 66 return i*8 + j 67 } 68 } 69 } 70 return len(one) * 8 71 } 72 73 // Address.ProxCmp compares the distances a->target and b->target. 74 // Returns -1 if a is closer to target, 1 if b is closer to target 75 // and 0 if they are equal. 76 func (target Address) ProxCmp(a, b Address) int { 77 for i := range target { 78 da := a[i] ^ target[i] 79 db := b[i] ^ target[i] 80 if da > db { 81 return 1 82 } else if da < db { 83 return -1 84 } 85 } 86 return 0 87 } 88 89 // randomAddressAt(address, prox) generates a random address 90 // at proximity order prox relative to address 91 // if prox is negative a random address is generated 92 func RandomAddressAt(self Address, prox int) (addr Address) { 93 addr = self 94 var pos int 95 if prox >= 0 { 96 pos = prox / 8 97 trans := prox % 8 98 transbytea := byte(0) 99 for j := 0; j <= trans; j++ { 100 transbytea |= 1 << uint8(7-j) 101 } 102 flipbyte := byte(1 << uint8(7-trans)) 103 transbyteb := transbytea ^ byte(255) 104 randbyte := byte(rand.Intn(255)) 105 addr[pos] = ((addr[pos] & transbytea) ^ flipbyte) | randbyte&transbyteb 106 } 107 for i := pos + 1; i < len(addr); i++ { 108 addr[i] = byte(rand.Intn(255)) 109 } 110 111 return 112 } 113 114 // KeyRange(a0, a1, proxLimit) returns the address inclusive address 115 // range that contain addresses closer to one than other 116 func KeyRange(one, other Address, proxLimit int) (start, stop Address) { 117 prox := proximity(one, other) 118 if prox >= proxLimit { 119 prox = proxLimit 120 } 121 start = CommonBitsAddrByte(one, other, byte(0x00), prox) 122 stop = CommonBitsAddrByte(one, other, byte(0xff), prox) 123 return 124 } 125 126 func CommonBitsAddrF(self, other Address, f func() byte, p int) (addr Address) { 127 prox := proximity(self, other) 128 var pos int 129 if p <= prox { 130 prox = p 131 } 132 pos = prox / 8 133 addr = self 134 trans := byte(prox % 8) 135 var transbytea byte 136 if p > prox { 137 transbytea = byte(0x7f) 138 } else { 139 transbytea = byte(0xff) 140 } 141 transbytea >>= trans 142 transbyteb := transbytea ^ byte(0xff) 143 addrpos := addr[pos] 144 addrpos &= transbyteb 145 if p > prox { 146 addrpos ^= byte(0x80 >> trans) 147 } 148 addrpos |= transbytea & f() 149 addr[pos] = addrpos 150 for i := pos + 1; i < len(addr); i++ { 151 addr[i] = f() 152 } 153 154 return 155 } 156 157 func CommonBitsAddr(self, other Address, prox int) (addr Address) { 158 return CommonBitsAddrF(self, other, func() byte { return byte(rand.Intn(255)) }, prox) 159 } 160 161 func CommonBitsAddrByte(self, other Address, b byte, prox int) (addr Address) { 162 return CommonBitsAddrF(self, other, func() byte { return b }, prox) 163 } 164 165 // randomAddressAt() generates a random address 166 func RandomAddress() Address { 167 return RandomAddressAt(Address{}, -1) 168 }