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