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  }