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