github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/longbits/long_bits.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package longbits
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/binary"
    11  	"encoding/hex"
    12  	"fmt"
    13  	"io"
    14  	"math/bits"
    15  	"strings"
    16  )
    17  
    18  var _ FoldableReader = Bits128{}
    19  
    20  const BitsStringPrefix = "0x"
    21  
    22  type Bits64 [8]byte
    23  
    24  func NewBits64(v uint64) Bits64 {
    25  	r := Bits64{}
    26  	binary.LittleEndian.PutUint64(r[:], v)
    27  	return r
    28  }
    29  
    30  func (v Bits64) WriteTo(w io.Writer) (int64, error) {
    31  	n, err := w.Write((v)[:])
    32  	return int64(n), err
    33  }
    34  
    35  func (v Bits64) CopyTo(p []byte) int {
    36  	return copy(p, (v)[:])
    37  }
    38  
    39  // TODO test for all ReadAt
    40  func (v Bits64) ReadAt(b []byte, off int64) (n int, err error) {
    41  	if n, err = VerifyReadAt(b, off, len(v)); err != nil || n == 0 {
    42  		return n, err
    43  	}
    44  	return copy(b, v[off:]), nil
    45  }
    46  
    47  func (v Bits64) CutOutUint64() uint64 {
    48  	return binary.LittleEndian.Uint64(v[:])
    49  }
    50  
    51  func (v Bits64) FoldToUint64() uint64 {
    52  	return binary.LittleEndian.Uint64(v[:])
    53  }
    54  
    55  func (v Bits64) FixedByteSize() int {
    56  	return len(v)
    57  }
    58  
    59  func (v Bits64) AsByteString() ByteString {
    60  	return ByteString(v[:])
    61  }
    62  
    63  func (v Bits64) String() string {
    64  	return bitsToStringDefault(v)
    65  }
    66  
    67  // deprecated // use longbits.AsBytes()
    68  func (v Bits64) AsBytes() []byte {
    69  	return v[:]
    70  }
    71  
    72  func (v Bits64) Compare(other Bits64) int {
    73  	return bytes.Compare(v[:], other[:])
    74  }
    75  
    76  /* Array size doesnt need to be aligned */
    77  func FoldToBits64(v []byte) (folded Bits64) {
    78  	if len(v) == 0 {
    79  		return folded
    80  	}
    81  
    82  	alignedLen := len(v) &^ (len(folded) - 1) // NB! len(folded) MUST be power of 2
    83  	copy(folded[:], v[alignedLen:])
    84  
    85  	for i := 0; i < alignedLen; i += len(folded) {
    86  		folded[0] ^= v[i+0]
    87  		folded[1] ^= v[i+1]
    88  		folded[2] ^= v[i+2]
    89  		folded[3] ^= v[i+3]
    90  		folded[4] ^= v[i+4]
    91  		folded[5] ^= v[i+5]
    92  		folded[6] ^= v[i+6]
    93  		folded[7] ^= v[i+7]
    94  	}
    95  	return folded
    96  }
    97  
    98  // CutOutBits64 either copies all bytes or picks evenly bytes from (v). Sizes do not need to be aligned.
    99  // WARNING! This is NOT compliant with cryptography standards, e.g. FIPS 180‑4 and SP 800-107
   100  func CutOutBits64(v []byte) (folded Bits64) {
   101  	if len(v) <= len(folded) {
   102  		copy(folded[:], v)
   103  		return folded
   104  	}
   105  
   106  	for i := range folded {
   107  		folded[i] = v[i*(len(v)-1)/(len(folded)-1)]
   108  	}
   109  	return folded
   110  }
   111  
   112  func NewBits128(lo, hi uint64) Bits128 {
   113  	r := Bits128{}
   114  	binary.LittleEndian.PutUint64(r[:8], lo)
   115  	binary.LittleEndian.PutUint64(r[8:], hi)
   116  	return r
   117  }
   118  
   119  type Bits128 [16]byte
   120  
   121  func (v Bits128) WriteTo(w io.Writer) (int64, error) {
   122  	n, err := w.Write((v)[:])
   123  	return int64(n), err
   124  }
   125  
   126  func (v Bits128) CopyTo(p []byte) int {
   127  	return copy(p, (v)[:])
   128  }
   129  
   130  func (v Bits128) ReadAt(b []byte, off int64) (n int, err error) {
   131  	n, err = VerifyReadAt(b, off, len(v))
   132  	if err != nil || n == 0 {
   133  		return n, err
   134  	}
   135  	return copy(b, v[off:]), nil
   136  }
   137  
   138  func (v Bits128) CutOutUint64() uint64 {
   139  	return CutOutUint64(v[:])
   140  }
   141  
   142  func (v Bits128) FoldToUint64() uint64 {
   143  	return FoldToUint64(v[:])
   144  }
   145  
   146  func (v Bits128) FixedByteSize() int {
   147  	return len(v)
   148  }
   149  
   150  func (v Bits128) String() string {
   151  	return bitsToStringDefault(v)
   152  }
   153  
   154  func (v Bits128) AsByteString() ByteString {
   155  	return ByteString(v[:])
   156  }
   157  
   158  // deprecated // use longbits.AsBytes()
   159  func (v Bits128) AsBytes() []byte {
   160  	return v[:]
   161  }
   162  
   163  func (v Bits128) Compare(other Bits128) int {
   164  	return bytes.Compare(v[:], other[:])
   165  }
   166  
   167  type Bits224 [28]byte
   168  
   169  func (v Bits224) WriteTo(w io.Writer) (int64, error) {
   170  	n, err := w.Write((v)[:])
   171  	return int64(n), err
   172  }
   173  
   174  func (v Bits224) CopyTo(p []byte) int {
   175  	return copy(p, (v)[:])
   176  }
   177  
   178  func (v Bits224) ReadAt(b []byte, off int64) (n int, err error) {
   179  	n, err = VerifyReadAt(b, off, len(v))
   180  	if err != nil || n == 0 {
   181  		return n, err
   182  	}
   183  	return copy(b, v[off:]), nil
   184  }
   185  
   186  func (v Bits224) CutOutUint64() uint64 {
   187  	return CutOutUint64(v[:])
   188  }
   189  
   190  func (v Bits224) FoldToUint64() uint64 {
   191  	return FoldToUint64(v[:])
   192  }
   193  
   194  func (v Bits224) FixedByteSize() int {
   195  	return len(v)
   196  }
   197  
   198  func (v Bits224) String() string {
   199  	return bitsToStringDefault(v)
   200  }
   201  
   202  // deprecated // use longbits.AsBytes()
   203  func (v Bits224) AsBytes() []byte {
   204  	return v[:]
   205  }
   206  
   207  func (v Bits224) AsByteString() ByteString {
   208  	return ByteString(v[:])
   209  }
   210  
   211  func (v Bits224) Compare(other Bits224) int {
   212  	return bytes.Compare(v[:], other[:])
   213  }
   214  
   215  type Bits256 [32]byte
   216  
   217  func (v Bits256) WriteTo(w io.Writer) (int64, error) {
   218  	n, err := w.Write((v)[:])
   219  	return int64(n), err
   220  }
   221  
   222  func (v Bits256) CopyTo(p []byte) int {
   223  	return copy(p, (v)[:])
   224  }
   225  
   226  func (v Bits256) ReadAt(b []byte, off int64) (n int, err error) {
   227  	n, err = VerifyReadAt(b, off, len(v))
   228  	if err != nil || n == 0 {
   229  		return n, err
   230  	}
   231  	return copy(b, v[off:]), nil
   232  }
   233  
   234  func (v Bits256) CutOutUint64() uint64 {
   235  	return CutOutUint64(v[:])
   236  }
   237  
   238  func (v Bits256) FoldToUint64() uint64 {
   239  	return FoldToUint64(v[:])
   240  }
   241  
   242  func (v Bits256) FoldToBits128() (r Bits128) {
   243  	for i := range r {
   244  		r[i] = v[i] ^ v[i+len(r)]
   245  	}
   246  	return r
   247  }
   248  
   249  func (v Bits256) FoldToBits224() Bits224 {
   250  	return v.TruncateToBits224()
   251  }
   252  
   253  // TruncateToBits224 returns leftmost bits, and it is compliant with cryptography standards, e.g. FIPS 180‑4 and SP 800-107
   254  func (v Bits256) TruncateToBits224() (r Bits224) {
   255  	copy(r[:], v[:])
   256  	return r
   257  }
   258  
   259  func (v Bits256) FixedByteSize() int {
   260  	return len(v)
   261  }
   262  
   263  func (v Bits256) String() string {
   264  	return bitsToStringDefault(v)
   265  }
   266  
   267  // deprecated // use longbits.AsBytes()
   268  func (v Bits256) AsBytes() []byte {
   269  	return v[:]
   270  }
   271  
   272  func (v Bits256) AsByteString() ByteString {
   273  	return ByteString(v[:])
   274  }
   275  
   276  func (v Bits256) Compare(other Bits256) int {
   277  	return bytes.Compare(v[:], other[:])
   278  }
   279  
   280  type Bits512 [64]byte
   281  
   282  func (v Bits512) WriteTo(w io.Writer) (int64, error) {
   283  	n, err := w.Write((v)[:])
   284  	return int64(n), err
   285  }
   286  
   287  func (v Bits512) CopyTo(p []byte) int {
   288  	return copy(p, (v)[:])
   289  }
   290  
   291  func (v Bits512) ReadAt(b []byte, off int64) (n int, err error) {
   292  	n, err = VerifyReadAt(b, off, len(v))
   293  	if err != nil || n == 0 {
   294  		return n, err
   295  	}
   296  	return copy(b, v[off:]), nil
   297  }
   298  
   299  func (v Bits512) CutOutUint64() uint64 {
   300  	return CutOutUint64(v[:])
   301  }
   302  
   303  func (v Bits512) FoldToUint64() uint64 {
   304  	return FoldToUint64(v[:])
   305  }
   306  
   307  func (v Bits512) FoldToBits256() (r Bits256) {
   308  	for i := range r {
   309  		r[i] = v[i] ^ v[i+len(r)]
   310  	}
   311  	return r
   312  }
   313  
   314  func (v Bits512) FoldToBits224() (r Bits224) {
   315  	for i := range r {
   316  		r[i] = v[i] ^ v[i+32]
   317  	}
   318  	return r
   319  }
   320  
   321  func (v Bits512) FixedByteSize() int {
   322  	return len(v)
   323  }
   324  
   325  func (v Bits512) String() string {
   326  	return bitsToStringDefault(v)
   327  }
   328  
   329  // deprecated // use longbits.AsBytes()
   330  func (v Bits512) AsBytes() []byte {
   331  	return v[:]
   332  }
   333  
   334  func (v Bits512) AsByteString() ByteString {
   335  	return ByteString(v[:])
   336  }
   337  
   338  func (v Bits512) Compare(other Bits512) int {
   339  	return bytes.Compare(v[:], other[:])
   340  }
   341  
   342  func CutOutUint64(v []byte) uint64 {
   343  	folded := CutOutBits64(v)
   344  	return folded.CutOutUint64()
   345  }
   346  
   347  func FoldToUint64(v []byte) uint64 {
   348  	folded := FoldToBits64(v)
   349  	return folded.FoldToUint64()
   350  }
   351  
   352  /*
   353  This implementation DOES NOT provide secure random!
   354  This function has a fixed implementation and MUST remain unchanged as some elements of Consensus rely on identical behavior of this functions.
   355  Array size must be aligned to 8 bytes.
   356  */
   357  func FillBitsWithStaticNoise(base uint32, v []byte) {
   358  
   359  	if bits.OnesCount32(base) < 8 {
   360  		base ^= 0x6206cc91 // add some noise
   361  	}
   362  
   363  	for i := uint32(0); i < uint32(len(v)); i += 8 {
   364  		var n = base + i>>3
   365  		u := uint64((^n) ^ (n << 16))
   366  		u |= (u + 1) << 31
   367  		u ^= u >> 1
   368  		t := v[i:]
   369  		binary.LittleEndian.PutUint64(t, u)
   370  	}
   371  }
   372  
   373  func bitsToStringDefault(s FoldableReader) string {
   374  	return BytesToDigestString(s, BitsStringPrefix)
   375  	// return BytesToGroupedString(s.AsBytes(), BitsStringPrefix, "_", 8)
   376  }
   377  
   378  func BytesToDigestString(s FoldableReader, prefix string) string {
   379  	return fmt.Sprintf("bits[%d]%s%08x", s.FixedByteSize()*8, prefix, s.FoldToUint64())
   380  }
   381  
   382  func BytesToGroupedString(s []byte, prefix string, separator string, everyN int) string {
   383  	if everyN == 0 || len(separator) == 0 {
   384  		return prefix + hex.EncodeToString(s)
   385  	}
   386  
   387  	buf := strings.Builder{}
   388  	buf.WriteString(prefix)
   389  	dst := make([]byte, hex.EncodedLen(len(s)))
   390  	hex.Encode(dst, s)
   391  
   392  	i := 0
   393  	for i < len(s) {
   394  		if i > 0 {
   395  			buf.WriteString(separator)
   396  		}
   397  		n := i + everyN
   398  		if i < len(s) {
   399  			buf.Write(dst[i:n])
   400  		} else {
   401  			buf.Write(dst[i:])
   402  			break
   403  		}
   404  		i = n
   405  	}
   406  	return buf.String()
   407  }
   408  
   409  func copyToFixedBits(dst, src []byte, expectedSize int) {
   410  	size := len(src)
   411  	if size != expectedSize {
   412  		panic(fmt.Sprintf("length mismatch, expected: %d, actual: %d", expectedSize, size))
   413  	}
   414  
   415  	copy(dst, src)
   416  }
   417  
   418  func NewBits64FromBytes(bytes []byte) Bits64 {
   419  	b := Bits64{}
   420  	copyToFixedBits(b[:], bytes, b.FixedByteSize())
   421  	return b
   422  }
   423  
   424  func NewBits128FromBytes(bytes []byte) Bits128 {
   425  	b := Bits128{}
   426  	copyToFixedBits(b[:], bytes, b.FixedByteSize())
   427  	return b
   428  }
   429  
   430  func NewBits224FromBytes(bytes []byte) Bits224 {
   431  	b := Bits224{}
   432  	copyToFixedBits(b[:], bytes, b.FixedByteSize())
   433  	return b
   434  }
   435  
   436  func NewBits256FromBytes(bytes []byte) Bits256 {
   437  	b := Bits256{}
   438  	copyToFixedBits(b[:], bytes, b.FixedByteSize())
   439  	return b
   440  }
   441  
   442  func NewBits512FromBytes(bytes []byte) Bits512 {
   443  	b := Bits512{}
   444  	copyToFixedBits(b[:], bytes, b.FixedByteSize())
   445  	return b
   446  }