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