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