github.com/maynardminer/ethereumprogpow@v1.8.23/swarm/pot/address.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package pot see doc.go
    18  package pot
    19  
    20  import (
    21  	"encoding/binary"
    22  	"fmt"
    23  	"math/rand"
    24  	"strconv"
    25  	"strings"
    26  
    27  	"github.com/ethereumprogpow/ethereumprogpow/common"
    28  )
    29  
    30  var (
    31  	zerosBin = Address{}.Bin()
    32  )
    33  
    34  // Address is an alias for common.Hash
    35  type Address common.Hash
    36  
    37  // NewAddressFromBytes constructs an Address from a byte slice
    38  func NewAddressFromBytes(b []byte) Address {
    39  	h := common.Hash{}
    40  	copy(h[:], b)
    41  	return Address(h)
    42  }
    43  
    44  func (a Address) String() string {
    45  	return fmt.Sprintf("%x", a[:])
    46  }
    47  
    48  // MarshalJSON Address serialisation
    49  func (a *Address) MarshalJSON() (out []byte, err error) {
    50  	return []byte(`"` + a.String() + `"`), nil
    51  }
    52  
    53  // UnmarshalJSON Address deserialisation
    54  func (a *Address) UnmarshalJSON(value []byte) error {
    55  	*a = Address(common.HexToHash(string(value[1 : len(value)-1])))
    56  	return nil
    57  }
    58  
    59  // Bin returns the string form of the binary representation of an address (only first 8 bits)
    60  func (a Address) Bin() string {
    61  	return ToBin(a[:])
    62  }
    63  
    64  // ToBin converts a byteslice to the string binary representation
    65  func ToBin(a []byte) string {
    66  	var bs []string
    67  	for _, b := range a {
    68  		bs = append(bs, fmt.Sprintf("%08b", b))
    69  	}
    70  	return strings.Join(bs, "")
    71  }
    72  
    73  // Bytes returns the Address as a byte slice
    74  func (a Address) Bytes() []byte {
    75  	return a[:]
    76  }
    77  
    78  // ProxCmp compares the distances a->target and b->target.
    79  // Returns -1 if a is closer to target, 1 if b is closer to target
    80  // and 0 if they are equal.
    81  func ProxCmp(a, x, y interface{}) int {
    82  	return proxCmp(ToBytes(a), ToBytes(x), ToBytes(y))
    83  }
    84  
    85  func proxCmp(a, x, y []byte) int {
    86  	for i := range a {
    87  		dx := x[i] ^ a[i]
    88  		dy := y[i] ^ a[i]
    89  		if dx > dy {
    90  			return 1
    91  		} else if dx < dy {
    92  			return -1
    93  		}
    94  	}
    95  	return 0
    96  }
    97  
    98  // RandomAddressAt (address, prox) generates a random address
    99  // at proximity order prox relative to address
   100  // if prox is negative a random address is generated
   101  func RandomAddressAt(self Address, prox int) (addr Address) {
   102  	addr = self
   103  	pos := -1
   104  	if prox >= 0 {
   105  		pos = prox / 8
   106  		trans := prox % 8
   107  		transbytea := byte(0)
   108  		for j := 0; j <= trans; j++ {
   109  			transbytea |= 1 << uint8(7-j)
   110  		}
   111  		flipbyte := byte(1 << uint8(7-trans))
   112  		transbyteb := transbytea ^ byte(255)
   113  		randbyte := byte(rand.Intn(255))
   114  		addr[pos] = ((addr[pos] & transbytea) ^ flipbyte) | randbyte&transbyteb
   115  	}
   116  	for i := pos + 1; i < len(addr); i++ {
   117  		addr[i] = byte(rand.Intn(255))
   118  	}
   119  
   120  	return
   121  }
   122  
   123  // RandomAddress generates a random address
   124  func RandomAddress() Address {
   125  	return RandomAddressAt(Address{}, -1)
   126  }
   127  
   128  // NewAddressFromString creates a byte slice from a string in binary representation
   129  func NewAddressFromString(s string) []byte {
   130  	ha := [32]byte{}
   131  
   132  	t := s + zerosBin[:len(zerosBin)-len(s)]
   133  	for i := 0; i < 4; i++ {
   134  		n, err := strconv.ParseUint(t[i*64:(i+1)*64], 2, 64)
   135  		if err != nil {
   136  			panic("wrong format: " + err.Error())
   137  		}
   138  		binary.BigEndian.PutUint64(ha[i*8:(i+1)*8], n)
   139  	}
   140  	return ha[:]
   141  }
   142  
   143  // BytesAddress is an interface for elements addressable by a byte slice
   144  type BytesAddress interface {
   145  	Address() []byte
   146  }
   147  
   148  // ToBytes turns the Val into bytes
   149  func ToBytes(v Val) []byte {
   150  	if v == nil {
   151  		return nil
   152  	}
   153  	b, ok := v.([]byte)
   154  	if !ok {
   155  		ba, ok := v.(BytesAddress)
   156  		if !ok {
   157  			panic(fmt.Sprintf("unsupported value type %T", v))
   158  		}
   159  		b = ba.Address()
   160  	}
   161  	return b
   162  }
   163  
   164  // DefaultPof returns a proximity order comparison operator function
   165  func DefaultPof(max int) func(one, other Val, pos int) (int, bool) {
   166  	return func(one, other Val, pos int) (int, bool) {
   167  		po, eq := proximityOrder(ToBytes(one), ToBytes(other), pos)
   168  		if po >= max {
   169  			eq = true
   170  			po = max
   171  		}
   172  		return po, eq
   173  	}
   174  }
   175  
   176  // proximityOrder returns two parameters:
   177  // 1. relative proximity order of the arguments one & other;
   178  // 2. boolean indicating whether the full match occurred (one == other).
   179  func proximityOrder(one, other []byte, pos int) (int, bool) {
   180  	for i := pos / 8; i < len(one); i++ {
   181  		if one[i] == other[i] {
   182  			continue
   183  		}
   184  		oxo := one[i] ^ other[i]
   185  		start := 0
   186  		if i == pos/8 {
   187  			start = pos % 8
   188  		}
   189  		for j := start; j < 8; j++ {
   190  			if (oxo>>uint8(7-j))&0x01 != 0 {
   191  				return i*8 + j, false
   192  			}
   193  		}
   194  	}
   195  	return len(one) * 8, true
   196  }
   197  
   198  // Label displays the node's key in binary format
   199  func Label(v Val) string {
   200  	if v == nil {
   201  		return "<nil>"
   202  	}
   203  	if s, ok := v.(fmt.Stringer); ok {
   204  		return s.String()
   205  	}
   206  	if b, ok := v.([]byte); ok {
   207  		return ToBin(b)
   208  	}
   209  	panic(fmt.Sprintf("unsupported value type %T", v))
   210  }