| 
									
										
										
										
											2018-08-14 16:03:56 +02:00
										 |  |  | package chunk | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 16:03:56 +02:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	DefaultSize   = 4096 | 
					
						
							|  |  |  | 	MaxPO         = 16 | 
					
						
							|  |  |  | 	AddressLength = 32 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	ErrChunkNotFound = errors.New("chunk not found") | 
					
						
							|  |  |  | 	ErrChunkInvalid  = errors.New("invalid chunk") | 
					
						
							| 
									
										
										
										
											2018-08-14 16:03:56 +02:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | type Chunk interface { | 
					
						
							|  |  |  | 	Address() Address | 
					
						
							|  |  |  | 	Data() []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type chunk struct { | 
					
						
							|  |  |  | 	addr  Address | 
					
						
							|  |  |  | 	sdata []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewChunk(addr Address, data []byte) *chunk { | 
					
						
							|  |  |  | 	return &chunk{ | 
					
						
							|  |  |  | 		addr:  addr, | 
					
						
							|  |  |  | 		sdata: data, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *chunk) Address() Address { | 
					
						
							|  |  |  | 	return c.addr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *chunk) Data() []byte { | 
					
						
							|  |  |  | 	return c.sdata | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *chunk) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("Address: %v Chunksize: %v", self.addr.Log(), len(self.sdata)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Address []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ZeroAddr = Address(common.Hash{}.Bytes()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a Address) Hex() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("%064x", []byte(a[:])) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a Address) Log() string { | 
					
						
							|  |  |  | 	if len(a[:]) < 8 { | 
					
						
							|  |  |  | 		return fmt.Sprintf("%x", []byte(a[:])) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("%016x", []byte(a[:8])) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a Address) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("%064x", []byte(a)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a Address) MarshalJSON() (out []byte, err error) { | 
					
						
							|  |  |  | 	return []byte(`"` + a.String() + `"`), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a *Address) UnmarshalJSON(value []byte) error { | 
					
						
							|  |  |  | 	s := string(value) | 
					
						
							|  |  |  | 	*a = make([]byte, 32) | 
					
						
							|  |  |  | 	h := common.Hex2Bytes(s[1 : len(s)-1]) | 
					
						
							|  |  |  | 	copy(*a, h) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Proximity returns the proximity order of the MSB distance between x and y | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The distance metric MSB(x, y) of two equal length byte sequences x an y is the | 
					
						
							|  |  |  | // value of the binary integer cast of the x^y, ie., x and y bitwise xor-ed. | 
					
						
							|  |  |  | // the binary cast is big endian: most significant bit first (=MSB). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Proximity(x, y) is a discrete logarithmic scaling of the MSB distance. | 
					
						
							|  |  |  | // It is defined as the reverse rank of the integer part of the base 2 | 
					
						
							|  |  |  | // logarithm of the distance. | 
					
						
							|  |  |  | // It is calculated by counting the number of common leading zeros in the (MSB) | 
					
						
							|  |  |  | // binary representation of the x^y. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // (0 farthest, 255 closest, 256 self) | 
					
						
							|  |  |  | func Proximity(one, other []byte) (ret int) { | 
					
						
							|  |  |  | 	b := (MaxPO-1)/8 + 1 | 
					
						
							|  |  |  | 	if b > len(one) { | 
					
						
							|  |  |  | 		b = len(one) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m := 8 | 
					
						
							|  |  |  | 	for i := 0; i < b; i++ { | 
					
						
							|  |  |  | 		oxo := one[i] ^ other[i] | 
					
						
							|  |  |  | 		for j := 0; j < m; j++ { | 
					
						
							|  |  |  | 			if (oxo>>uint8(7-j))&0x01 != 0 { | 
					
						
							|  |  |  | 				return i*8 + j | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return MaxPO | 
					
						
							|  |  |  | } |