github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/swarm/pot/address.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package pot see doc.go 18 package pot 19 20 import ( 21 "encoding/binary" 22 "fmt" 23 "math/rand" 24 "strconv" 25 "strings" 26 27 "github.com/ethereum/go-ethereum/common" 28 ) 29 30 var ( 31 zerosBin = Address{}.Bin() 32 ) 33 34 // Address is an alias for common.Hash 35 type Address common.Hash 36 37 // NewAddressFromBytes constructs an Address from a byte slice 38 func NewAddressFromBytes(b []byte) Address { 39 h := common.Hash{} 40 copy(h[:], b) 41 return Address(h) 42 } 43 44 func (a Address) IsZero() bool { 45 return a.Bin() == zerosBin 46 } 47 48 func (a Address) String() string { 49 return fmt.Sprintf("%x", a[:]) 50 } 51 52 // MarshalJSON Address serialisation 53 func (a *Address) MarshalJSON() (out []byte, err error) { 54 return []byte(`"` + a.String() + `"`), nil 55 } 56 57 // UnmarshalJSON Address deserialisation 58 func (a *Address) UnmarshalJSON(value []byte) error { 59 *a = Address(common.HexToHash(string(value[1 : len(value)-1]))) 60 return nil 61 } 62 63 // Bin returns the string form of the binary representation of an address (only first 8 bits) 64 func (a Address) Bin() string { 65 return ToBin(a[:]) 66 } 67 68 // ToBin converts a byteslice to the string binary representation 69 func ToBin(a []byte) string { 70 var bs []string 71 for _, b := range a { 72 bs = append(bs, fmt.Sprintf("%08b", b)) 73 } 74 return strings.Join(bs, "") 75 } 76 77 // Bytes returns the Address as a byte slice 78 func (a Address) Bytes() []byte { 79 return a[:] 80 } 81 82 // ProxCmp compares the distances a->target and b->target. 83 // Returns -1 if a is closer to target, 1 if b is closer to target 84 // and 0 if they are equal. 85 func ProxCmp(a, x, y interface{}) int { 86 return proxCmp(ToBytes(a), ToBytes(x), ToBytes(y)) 87 } 88 89 func proxCmp(a, x, y []byte) int { 90 for i := range a { 91 dx := x[i] ^ a[i] 92 dy := y[i] ^ a[i] 93 if dx > dy { 94 return 1 95 } else if dx < dy { 96 return -1 97 } 98 } 99 return 0 100 } 101 102 // RandomAddressAt (address, prox) generates a random address 103 // at proximity order prox relative to address 104 // if prox is negative a random address is generated 105 func RandomAddressAt(self Address, prox int) (addr Address) { 106 addr = self 107 pos := -1 108 if prox >= 0 { 109 pos = prox / 8 110 trans := prox % 8 111 transbytea := byte(0) 112 for j := 0; j <= trans; j++ { 113 transbytea |= 1 << uint8(7-j) 114 } 115 flipbyte := byte(1 << uint8(7-trans)) 116 transbyteb := transbytea ^ byte(255) 117 randbyte := byte(rand.Intn(255)) 118 addr[pos] = ((addr[pos] & transbytea) ^ flipbyte) | randbyte&transbyteb 119 } 120 for i := pos + 1; i < len(addr); i++ { 121 addr[i] = byte(rand.Intn(255)) 122 } 123 124 return 125 } 126 127 // RandomAddress generates a random address 128 func RandomAddress() Address { 129 return RandomAddressAt(Address{}, -1) 130 } 131 132 // NewAddressFromString creates a byte slice from a string in binary representation 133 func NewAddressFromString(s string) []byte { 134 ha := [32]byte{} 135 136 t := s + zerosBin[:len(zerosBin)-len(s)] 137 for i := 0; i < 4; i++ { 138 n, err := strconv.ParseUint(t[i*64:(i+1)*64], 2, 64) 139 if err != nil { 140 panic("wrong format: " + err.Error()) 141 } 142 binary.BigEndian.PutUint64(ha[i*8:(i+1)*8], n) 143 } 144 return ha[:] 145 } 146 147 // BytesAddress is an interface for elements addressable by a byte slice 148 type BytesAddress interface { 149 Address() []byte 150 } 151 152 // ToBytes turns the Val into bytes 153 func ToBytes(v Val) []byte { 154 if v == nil { 155 return nil 156 } 157 b, ok := v.([]byte) 158 if !ok { 159 ba, ok := v.(BytesAddress) 160 if !ok { 161 panic(fmt.Sprintf("unsupported value type %T", v)) 162 } 163 b = ba.Address() 164 } 165 return b 166 } 167 168 // DefaultPof returns a proximity order comparison operator function 169 // where all 170 func DefaultPof(max int) func(one, other Val, pos int) (int, bool) { 171 return func(one, other Val, pos int) (int, bool) { 172 po, eq := proximityOrder(ToBytes(one), ToBytes(other), pos) 173 if po >= max { 174 eq = true 175 po = max 176 } 177 return po, eq 178 } 179 } 180 181 func proximityOrder(one, other []byte, pos int) (int, bool) { 182 for i := pos / 8; i < len(one); i++ { 183 if one[i] == other[i] { 184 continue 185 } 186 oxo := one[i] ^ other[i] 187 start := 0 188 if i == pos/8 { 189 start = pos % 8 190 } 191 for j := start; j < 8; j++ { 192 if (oxo>>uint8(7-j))&0x01 != 0 { 193 return i*8 + j, false 194 } 195 } 196 } 197 return len(one) * 8, true 198 } 199 200 // Label displays the node's key in binary format 201 func Label(v Val) string { 202 if v == nil { 203 return "<nil>" 204 } 205 if s, ok := v.(fmt.Stringer); ok { 206 return s.String() 207 } 208 if b, ok := v.([]byte); ok { 209 return ToBin(b) 210 } 211 panic(fmt.Sprintf("unsupported value type %T", v)) 212 }