github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/pot/address.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:48</date> 10 //</624342676749160448> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 // 29 package pot 30 31 import ( 32 "encoding/binary" 33 "fmt" 34 "math/rand" 35 "strconv" 36 "strings" 37 38 "github.com/ethereum/go-ethereum/common" 39 ) 40 41 var ( 42 zerosBin = Address{}.Bin() 43 ) 44 45 // 46 type Address common.Hash 47 48 // 49 func NewAddressFromBytes(b []byte) Address { 50 h := common.Hash{} 51 copy(h[:], b) 52 return Address(h) 53 } 54 55 func (a Address) IsZero() bool { 56 return a.Bin() == zerosBin 57 } 58 59 func (a Address) String() string { 60 return fmt.Sprintf("%x", a[:]) 61 } 62 63 // 64 func (a *Address) MarshalJSON() (out []byte, err error) { 65 return []byte(`"` + a.String() + `"`), nil 66 } 67 68 // 69 func (a *Address) UnmarshalJSON(value []byte) error { 70 *a = Address(common.HexToHash(string(value[1 : len(value)-1]))) 71 return nil 72 } 73 74 // 75 func (a Address) Bin() string { 76 return ToBin(a[:]) 77 } 78 79 // 80 func ToBin(a []byte) string { 81 var bs []string 82 for _, b := range a { 83 bs = append(bs, fmt.Sprintf("%08b", b)) 84 } 85 return strings.Join(bs, "") 86 } 87 88 // 89 func (a Address) Bytes() []byte { 90 return a[:] 91 } 92 93 /* 94 95 96 97 98 99 100 101 102 103 104 105 106 107 */ 108 109 func proximity(one, other Address) (ret int, eq bool) { 110 return posProximity(one, other, 0) 111 } 112 113 // 114 // 115 func posProximity(one, other Address, pos int) (ret int, eq bool) { 116 for i := pos / 8; i < len(one); i++ { 117 if one[i] == other[i] { 118 continue 119 } 120 oxo := one[i] ^ other[i] 121 start := 0 122 if i == pos/8 { 123 start = pos % 8 124 } 125 for j := start; j < 8; j++ { 126 if (oxo>>uint8(7-j))&0x01 != 0 { 127 return i*8 + j, false 128 } 129 } 130 } 131 return len(one) * 8, true 132 } 133 134 // 135 // 136 // 137 func ProxCmp(a, x, y interface{}) int { 138 return proxCmp(ToBytes(a), ToBytes(x), ToBytes(y)) 139 } 140 141 func proxCmp(a, x, y []byte) int { 142 for i := range a { 143 dx := x[i] ^ a[i] 144 dy := y[i] ^ a[i] 145 if dx > dy { 146 return 1 147 } else if dx < dy { 148 return -1 149 } 150 } 151 return 0 152 } 153 154 // 155 // 156 // 157 func RandomAddressAt(self Address, prox int) (addr Address) { 158 addr = self 159 pos := -1 160 if prox >= 0 { 161 pos = prox / 8 162 trans := prox % 8 163 transbytea := byte(0) 164 for j := 0; j <= trans; j++ { 165 transbytea |= 1 << uint8(7-j) 166 } 167 flipbyte := byte(1 << uint8(7-trans)) 168 transbyteb := transbytea ^ byte(255) 169 randbyte := byte(rand.Intn(255)) 170 addr[pos] = ((addr[pos] & transbytea) ^ flipbyte) | randbyte&transbyteb 171 } 172 for i := pos + 1; i < len(addr); i++ { 173 addr[i] = byte(rand.Intn(255)) 174 } 175 176 return 177 } 178 179 // 180 func RandomAddress() Address { 181 return RandomAddressAt(Address{}, -1) 182 } 183 184 // 185 func NewAddressFromString(s string) []byte { 186 ha := [32]byte{} 187 188 t := s + zerosBin[:len(zerosBin)-len(s)] 189 for i := 0; i < 4; i++ { 190 n, err := strconv.ParseUint(t[i*64:(i+1)*64], 2, 64) 191 if err != nil { 192 panic("wrong format: " + err.Error()) 193 } 194 binary.BigEndian.PutUint64(ha[i*8:(i+1)*8], n) 195 } 196 return ha[:] 197 } 198 199 // 200 type BytesAddress interface { 201 Address() []byte 202 } 203 204 // 205 func ToBytes(v Val) []byte { 206 if v == nil { 207 return nil 208 } 209 b, ok := v.([]byte) 210 if !ok { 211 ba, ok := v.(BytesAddress) 212 if !ok { 213 panic(fmt.Sprintf("unsupported value type %T", v)) 214 } 215 b = ba.Address() 216 } 217 return b 218 } 219 220 // 221 // 222 func DefaultPof(max int) func(one, other Val, pos int) (int, bool) { 223 return func(one, other Val, pos int) (int, bool) { 224 po, eq := proximityOrder(ToBytes(one), ToBytes(other), pos) 225 if po >= max { 226 eq = true 227 po = max 228 } 229 return po, eq 230 } 231 } 232 233 func proximityOrder(one, other []byte, pos int) (int, bool) { 234 for i := pos / 8; i < len(one); i++ { 235 if one[i] == other[i] { 236 continue 237 } 238 oxo := one[i] ^ other[i] 239 start := 0 240 if i == pos/8 { 241 start = pos % 8 242 } 243 for j := start; j < 8; j++ { 244 if (oxo>>uint8(7-j))&0x01 != 0 { 245 return i*8 + j, false 246 } 247 } 248 } 249 return len(one) * 8, true 250 } 251 252 // 253 func Label(v Val) string { 254 if v == nil { 255 return "<nil>" 256 } 257 if s, ok := v.(fmt.Stringer); ok { 258 return s.String() 259 } 260 if b, ok := v.([]byte); ok { 261 return ToBin(b) 262 } 263 panic(fmt.Sprintf("unsupported value type %T", v)) 264 } 265