github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:44</date>
    10  //</624450116119433216>
    11  
    12  
    13  //包装罐见Go医生
    14  package pot
    15  
    16  import (
    17  	"encoding/binary"
    18  	"fmt"
    19  	"math/rand"
    20  	"strconv"
    21  	"strings"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  )
    25  
    26  var (
    27  	zerosBin = Address{}.Bin()
    28  )
    29  
    30  //地址是common.hash的别名
    31  type Address common.Hash
    32  
    33  //newAddressFromBytes从字节片构造地址
    34  func NewAddressFromBytes(b []byte) Address {
    35  	h := common.Hash{}
    36  	copy(h[:], b)
    37  	return Address(h)
    38  }
    39  
    40  func (a Address) String() string {
    41  	return fmt.Sprintf("%x", a[:])
    42  }
    43  
    44  //marshaljson地址序列化
    45  func (a *Address) MarshalJSON() (out []byte, err error) {
    46  	return []byte(`"` + a.String() + `"`), nil
    47  }
    48  
    49  //取消标记JSON地址反序列化
    50  func (a *Address) UnmarshalJSON(value []byte) error {
    51  	*a = Address(common.HexToHash(string(value[1 : len(value)-1])))
    52  	return nil
    53  }
    54  
    55  //bin返回地址的二进制表示的字符串形式(仅前8位)
    56  func (a Address) Bin() string {
    57  	return ToBin(a[:])
    58  }
    59  
    60  //Tobin将字节片转换为字符串二进制表示形式
    61  func ToBin(a []byte) string {
    62  	var bs []string
    63  	for _, b := range a {
    64  		bs = append(bs, fmt.Sprintf("%08b", b))
    65  	}
    66  	return strings.Join(bs, "")
    67  }
    68  
    69  //字节以字节片的形式返回地址
    70  func (a Address) Bytes() []byte {
    71  	return a[:]
    72  }
    73  
    74  //procmp比较距离a->target和b->target。
    75  //如果a接近目标返回-1,如果b接近目标返回1
    76  //如果相等,则为0。
    77  func ProxCmp(a, x, y interface{}) int {
    78  	return proxCmp(ToBytes(a), ToBytes(x), ToBytes(y))
    79  }
    80  
    81  func proxCmp(a, x, y []byte) int {
    82  	for i := range a {
    83  		dx := x[i] ^ a[i]
    84  		dy := y[i] ^ a[i]
    85  		if dx > dy {
    86  			return 1
    87  		} else if dx < dy {
    88  			return -1
    89  		}
    90  	}
    91  	return 0
    92  }
    93  
    94  //randomaddressat(地址,代理)生成随机地址
    95  //在接近顺序,相对于地址的代理
    96  //如果prox为负,则生成随机地址。
    97  func RandomAddressAt(self Address, prox int) (addr Address) {
    98  	addr = self
    99  	pos := -1
   100  	if prox >= 0 {
   101  		pos = prox / 8
   102  		trans := prox % 8
   103  		transbytea := byte(0)
   104  		for j := 0; j <= trans; j++ {
   105  			transbytea |= 1 << uint8(7-j)
   106  		}
   107  		flipbyte := byte(1 << uint8(7-trans))
   108  		transbyteb := transbytea ^ byte(255)
   109  		randbyte := byte(rand.Intn(255))
   110  		addr[pos] = ((addr[pos] & transbytea) ^ flipbyte) | randbyte&transbyteb
   111  	}
   112  	for i := pos + 1; i < len(addr); i++ {
   113  		addr[i] = byte(rand.Intn(255))
   114  	}
   115  
   116  	return
   117  }
   118  
   119  //random address生成随机地址
   120  func RandomAddress() Address {
   121  	return RandomAddressAt(Address{}, -1)
   122  }
   123  
   124  //newAddressFromString从二进制表示的字符串创建字节片
   125  func NewAddressFromString(s string) []byte {
   126  	ha := [32]byte{}
   127  
   128  	t := s + zerosBin[:len(zerosBin)-len(s)]
   129  	for i := 0; i < 4; i++ {
   130  		n, err := strconv.ParseUint(t[i*64:(i+1)*64], 2, 64)
   131  		if err != nil {
   132  			panic("wrong format: " + err.Error())
   133  		}
   134  		binary.BigEndian.PutUint64(ha[i*8:(i+1)*8], n)
   135  	}
   136  	return ha[:]
   137  }
   138  
   139  //BytesAddress是一个接口,用于按字节片寻址的元素
   140  type BytesAddress interface {
   141  	Address() []byte
   142  }
   143  
   144  //tobytes将val转换为字节
   145  func ToBytes(v Val) []byte {
   146  	if v == nil {
   147  		return nil
   148  	}
   149  	b, ok := v.([]byte)
   150  	if !ok {
   151  		ba, ok := v.(BytesAddress)
   152  		if !ok {
   153  			panic(fmt.Sprintf("unsupported value type %T", v))
   154  		}
   155  		b = ba.Address()
   156  	}
   157  	return b
   158  }
   159  
   160  //defaultpof返回一个接近顺序比较运算符函数
   161  func DefaultPof(max int) func(one, other Val, pos int) (int, bool) {
   162  	return func(one, other Val, pos int) (int, bool) {
   163  		po, eq := proximityOrder(ToBytes(one), ToBytes(other), pos)
   164  		if po >= max {
   165  			eq = true
   166  			po = max
   167  		}
   168  		return po, eq
   169  	}
   170  }
   171  
   172  //接近顺序返回两个参数:
   173  //1。一个和另一个参数的相对接近顺序;
   174  //2。布尔值,指示是否发生完全匹配(一个=另一个)。
   175  func proximityOrder(one, other []byte, pos int) (int, bool) {
   176  	for i := pos / 8; i < len(one); i++ {
   177  		if one[i] == other[i] {
   178  			continue
   179  		}
   180  		oxo := one[i] ^ other[i]
   181  		start := 0
   182  		if i == pos/8 {
   183  			start = pos % 8
   184  		}
   185  		for j := start; j < 8; j++ {
   186  			if (oxo>>uint8(7-j))&0x01 != 0 {
   187  				return i*8 + j, false
   188  			}
   189  		}
   190  	}
   191  	return len(one) * 8, true
   192  }
   193  
   194  //标签以二进制格式显示节点的密钥
   195  func Label(v Val) string {
   196  	if v == nil {
   197  		return "<nil>"
   198  	}
   199  	if s, ok := v.(fmt.Stringer); ok {
   200  		return s.String()
   201  	}
   202  	if b, ok := v.([]byte); ok {
   203  		return ToBin(b)
   204  	}
   205  	panic(fmt.Sprintf("unsupported value type %T", v))
   206  }
   207