108
vendor/github.com/holiman/bloomfilter/v2/binarymarshaler.go
generated
vendored
Normal file
108
vendor/github.com/holiman/bloomfilter/v2/binarymarshaler.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha512"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// headerMagic is used to disambiguate between this package and the original
|
||||
// steakknife implementation.
|
||||
// Since the key hashing algorithm has changed, the format is no longer
|
||||
// binary compatible
|
||||
var version = []byte("v02\n")
|
||||
var headerMagic = append([]byte{0, 0, 0, 0, 0, 0, 0, 0}, version...)
|
||||
|
||||
// counter is a utility to count bytes written
|
||||
type counter struct {
|
||||
bytes int
|
||||
}
|
||||
|
||||
func (c *counter) Write(p []byte) (n int, err error) {
|
||||
count := len(p)
|
||||
c.bytes += count
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// conforms to encoding.BinaryMarshaler
|
||||
|
||||
// MarshallToWriter marshalls the filter into the given io.Writer
|
||||
// Binary layout (Little Endian):
|
||||
//
|
||||
// k 1 uint64
|
||||
// n 1 uint64
|
||||
// m 1 uint64
|
||||
// keys [k]uint64
|
||||
// bits [(m+63)/64]uint64
|
||||
// hash sha384 (384 bits == 48 bytes)
|
||||
//
|
||||
// size = (3 + k + (m+63)/64) * 8 bytes
|
||||
//
|
||||
func (f *Filter) MarshallToWriter(out io.Writer) (int, [sha512.Size384]byte, error) {
|
||||
var (
|
||||
c = &counter{0}
|
||||
hasher = sha512.New384()
|
||||
mw = io.MultiWriter(out, hasher, c)
|
||||
hash [sha512.Size384]byte
|
||||
)
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
if _, err := mw.Write(headerMagic); err != nil {
|
||||
return c.bytes, hash, err
|
||||
}
|
||||
if err := binary.Write(mw, binary.LittleEndian, []uint64{f.K(), f.n, f.m}); err != nil {
|
||||
return c.bytes, hash, err
|
||||
}
|
||||
if err := binary.Write(mw, binary.LittleEndian, f.keys); err != nil {
|
||||
return c.bytes, hash, err
|
||||
}
|
||||
// Write it in chunks of 5% (but at least 4K). Otherwise, the binary.Write will allocate a
|
||||
// same-size slice of bytes, doubling the memory usage
|
||||
var chunkSize = len(f.bits) / 20
|
||||
if chunkSize < 512 {
|
||||
chunkSize = 512 // Min 4K bytes (512 uint64s)
|
||||
}
|
||||
buf := make([]byte, chunkSize*8)
|
||||
for start := 0; start < len(f.bits); {
|
||||
end := start + chunkSize
|
||||
if end > len(f.bits) {
|
||||
end = len(f.bits)
|
||||
}
|
||||
for i, x := range f.bits[start:end] {
|
||||
binary.LittleEndian.PutUint64(buf[8*i:], x)
|
||||
}
|
||||
if _, err := mw.Write(buf[0 : (end-start)*8]); err != nil {
|
||||
return c.bytes, hash, err
|
||||
}
|
||||
start = end
|
||||
}
|
||||
// Now we stop using the multiwriter, pick out the hash of what we've
|
||||
// written so far, and then write the hash to the output
|
||||
hashbytes := hasher.Sum(nil)
|
||||
copy(hash[:], hashbytes[:sha512.Size384])
|
||||
err := binary.Write(out, binary.LittleEndian, hashbytes)
|
||||
return c.bytes + len(hashbytes), hash, err
|
||||
}
|
||||
|
||||
// MarshalBinary converts a Filter into []bytes
|
||||
func (f *Filter) MarshalBinary() (data []byte, err error) {
|
||||
buf := new(bytes.Buffer)
|
||||
_, _, err = f.MarshallToWriter(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = buf.Bytes()
|
||||
return data, nil
|
||||
}
|
||||
130
vendor/github.com/holiman/bloomfilter/v2/binaryunmarshaler.go
generated
vendored
Normal file
130
vendor/github.com/holiman/bloomfilter/v2/binaryunmarshaler.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha512"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
func unmarshalBinaryHeader(r io.Reader) (k, n, m uint64, err error) {
|
||||
magic := make([]byte, len(headerMagic))
|
||||
if _, err := io.ReadFull(r, magic); err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
if !bytes.Equal(magic, headerMagic) {
|
||||
return 0, 0, 0, fmt.Errorf("incompatible version (wrong magic), got %x", magic)
|
||||
}
|
||||
var knm = make([]uint64, 3)
|
||||
err = binary.Read(r, binary.LittleEndian, knm)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
k = knm[0]
|
||||
n = knm[1]
|
||||
m = knm[2]
|
||||
if k < KMin {
|
||||
return 0, 0, 0, fmt.Errorf("keys must have length %d or greater (was %d)", KMin, k)
|
||||
}
|
||||
if m < MMin {
|
||||
return 0, 0, 0, fmt.Errorf("number of bits in the filter must be >= %d (was %d)", MMin, m)
|
||||
}
|
||||
return k, n, m, err
|
||||
}
|
||||
|
||||
func unmarshalBinaryBits(r io.Reader, m uint64) (bits []uint64, err error) {
|
||||
bits, err = newBits(m)
|
||||
if err != nil {
|
||||
return bits, err
|
||||
}
|
||||
bs := make([]byte, 8)
|
||||
for i := 0; i < len(bits) && err == nil; i++ {
|
||||
_, err = io.ReadFull(r, bs)
|
||||
bits[i] = binary.LittleEndian.Uint64(bs)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bits, nil
|
||||
}
|
||||
|
||||
func unmarshalBinaryKeys(r io.Reader, k uint64) (keys []uint64, err error) {
|
||||
keys = make([]uint64, k)
|
||||
err = binary.Read(r, binary.LittleEndian, keys)
|
||||
return keys, err
|
||||
}
|
||||
|
||||
// hashingReader can be used to read from a reader, and simultaneously
|
||||
// do a hash on the bytes that were read
|
||||
type hashingReader struct {
|
||||
reader io.Reader
|
||||
hasher hash.Hash
|
||||
tot int64
|
||||
}
|
||||
|
||||
func (h *hashingReader) Read(p []byte) (n int, err error) {
|
||||
n, err = h.reader.Read(p)
|
||||
h.tot += int64(n)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
_, _ = h.hasher.Write(p[:n])
|
||||
return n, err
|
||||
}
|
||||
|
||||
// UnmarshalBinary converts []bytes into a Filter
|
||||
// conforms to encoding.BinaryUnmarshaler
|
||||
func (f *Filter) UnmarshalBinary(data []byte) (err error) {
|
||||
buf := bytes.NewBuffer(data)
|
||||
_, err = f.UnmarshalFromReader(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *Filter) UnmarshalFromReader(input io.Reader) (n int64, err error) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
buf := &hashingReader{
|
||||
reader: input,
|
||||
hasher: sha512.New384(),
|
||||
}
|
||||
var k uint64
|
||||
k, f.n, f.m, err = unmarshalBinaryHeader(buf)
|
||||
if err != nil {
|
||||
return buf.tot, err
|
||||
}
|
||||
|
||||
f.keys, err = unmarshalBinaryKeys(buf, k)
|
||||
if err != nil {
|
||||
return buf.tot, err
|
||||
}
|
||||
f.bits, err = unmarshalBinaryBits(buf, f.m)
|
||||
if err != nil {
|
||||
return buf.tot, err
|
||||
}
|
||||
|
||||
// Only the hash remains to be read now
|
||||
// so abort the hasher at this point
|
||||
gotHash := buf.hasher.Sum(nil)
|
||||
expHash := make([]byte, sha512.Size384)
|
||||
err = binary.Read(buf, binary.LittleEndian, expHash)
|
||||
if err != nil {
|
||||
return buf.tot, err
|
||||
}
|
||||
if !bytes.Equal(gotHash, expHash) {
|
||||
return buf.tot, errHashMismatch
|
||||
}
|
||||
return buf.tot, nil
|
||||
}
|
||||
145
vendor/github.com/holiman/bloomfilter/v2/bloomfilter.go
generated
vendored
Normal file
145
vendor/github.com/holiman/bloomfilter/v2/bloomfilter.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
// Copyright © 2020 Martin Holst Swende, continued on the work of Barry Allard
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"hash"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
errHashMismatch = errors.New("hash mismatch, bloom filter corruption or wrong version")
|
||||
)
|
||||
|
||||
// Filter is an opaque Bloom filter type
|
||||
type Filter struct {
|
||||
lock sync.RWMutex
|
||||
bits []uint64
|
||||
keys []uint64
|
||||
m uint64 // number of bits the "bits" field should recognize
|
||||
n uint64 // number of inserted elements
|
||||
}
|
||||
|
||||
// M is the size of Bloom filter, in bits
|
||||
func (f *Filter) M() uint64 {
|
||||
return f.m
|
||||
}
|
||||
|
||||
// K is the count of keys
|
||||
func (f *Filter) K() uint64 {
|
||||
return uint64(len(f.keys))
|
||||
}
|
||||
|
||||
// Add a hashable item, v, to the filter
|
||||
func (f *Filter) Add(v hash.Hash64) {
|
||||
f.AddHash(v.Sum64())
|
||||
}
|
||||
|
||||
// rotation sets how much to rotate the hash on each filter iteration. This
|
||||
// is somewhat randomly set to a prime on the lower segment of 64. At 17, the cycle
|
||||
// does not repeat for quite a while, but even for low number of filters the
|
||||
// changes are quite rapid
|
||||
const rotation = 17
|
||||
|
||||
// Adds an already hashes item to the filter.
|
||||
// Identical to Add (but slightly faster)
|
||||
func (f *Filter) AddHash(hash uint64) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
var (
|
||||
i uint64
|
||||
)
|
||||
for n := 0; n < len(f.keys); n++ {
|
||||
hash = ((hash << rotation) | (hash >> (64 - rotation))) ^ f.keys[n]
|
||||
i = hash % f.m
|
||||
f.bits[i>>6] |= 1 << uint(i&0x3f)
|
||||
}
|
||||
f.n++
|
||||
}
|
||||
|
||||
// ContainsHash tests if f contains the (already hashed) key
|
||||
// Identical to Contains but slightly faster
|
||||
func (f *Filter) ContainsHash(hash uint64) bool {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
var (
|
||||
i uint64
|
||||
r = uint64(1)
|
||||
)
|
||||
for n := 0; n < len(f.keys) && r != 0; n++ {
|
||||
hash = ((hash << rotation) | (hash >> (64 - rotation))) ^ f.keys[n]
|
||||
i = hash % f.m
|
||||
r &= (f.bits[i>>6] >> uint(i&0x3f)) & 1
|
||||
}
|
||||
return r != 0
|
||||
}
|
||||
|
||||
// Contains tests if f contains v
|
||||
// false: f definitely does not contain value v
|
||||
// true: f maybe contains value v
|
||||
func (f *Filter) Contains(v hash.Hash64) bool {
|
||||
return f.ContainsHash(v.Sum64())
|
||||
}
|
||||
|
||||
// Copy f to a new Bloom filter
|
||||
func (f *Filter) Copy() (*Filter, error) {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
out, err := f.NewCompatible()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(out.bits, f.bits)
|
||||
out.n = f.n
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UnionInPlace merges Bloom filter f2 into f
|
||||
func (f *Filter) UnionInPlace(f2 *Filter) error {
|
||||
if !f.IsCompatible(f2) {
|
||||
return errors.New("incompatible bloom filters")
|
||||
}
|
||||
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for i, bitword := range f2.bits {
|
||||
f.bits[i] |= bitword
|
||||
}
|
||||
// Also update the counters
|
||||
f.n += f2.n
|
||||
return nil
|
||||
}
|
||||
|
||||
// Union merges f2 and f2 into a new Filter out
|
||||
func (f *Filter) Union(f2 *Filter) (out *Filter, err error) {
|
||||
if !f.IsCompatible(f2) {
|
||||
return nil, errors.New("incompatible bloom filters")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
out, err = f.NewCompatible()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, bitword := range f2.bits {
|
||||
out.bits[i] = f.bits[i] | bitword
|
||||
}
|
||||
// Also update the counters
|
||||
out.n = f.n + f2.n
|
||||
return out, nil
|
||||
}
|
||||
30
vendor/github.com/holiman/bloomfilter/v2/conformance.go
generated
vendored
Normal file
30
vendor/github.com/holiman/bloomfilter/v2/conformance.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
// compile-time conformance tests
|
||||
var (
|
||||
_ encoding.BinaryMarshaler = (*Filter)(nil)
|
||||
_ encoding.BinaryUnmarshaler = (*Filter)(nil)
|
||||
_ io.ReaderFrom = (*Filter)(nil)
|
||||
_ io.WriterTo = (*Filter)(nil)
|
||||
_ gob.GobDecoder = (*Filter)(nil)
|
||||
_ gob.GobEncoder = (*Filter)(nil)
|
||||
_ json.Marshaler = (*Filter)(nil)
|
||||
_ json.Unmarshaler = (*Filter)(nil)
|
||||
)
|
||||
131
vendor/github.com/holiman/bloomfilter/v2/fileio.go
generated
vendored
Normal file
131
vendor/github.com/holiman/bloomfilter/v2/fileio.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
_ "encoding/gob" // make sure gob is available
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ReadFrom r and overwrite f with new Bloom filter data
|
||||
func (f *Filter) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
f2, n, err := ReadFrom(r)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.m = f2.m
|
||||
f.n = f2.n
|
||||
f.bits = f2.bits
|
||||
f.keys = f2.keys
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// ReadFrom Reader r into a lossless-compressed Bloom filter f
|
||||
func ReadFrom(r io.Reader) (f *Filter, n int64, err error) {
|
||||
f = new(Filter)
|
||||
rawR, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
defer rawR.Close()
|
||||
n, err = f.UnmarshalFromReader(rawR)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
return f, n, nil
|
||||
}
|
||||
|
||||
// ReadFile from filename into a lossless-compressed Bloom Filter f
|
||||
// Suggested file extension: .bf.gz
|
||||
func ReadFile(filename string) (f *Filter, n int64, err error) {
|
||||
r, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
return ReadFrom(r)
|
||||
}
|
||||
|
||||
// WriteTo a Writer w from lossless-compressed Bloom Filter f
|
||||
func (f *Filter) WriteTo(w io.Writer) (n int64, err error) {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
rawW := gzip.NewWriter(w)
|
||||
defer rawW.Close()
|
||||
|
||||
intN, _, err := f.MarshallToWriter(rawW)
|
||||
//intN, _, err := f.MarshallToWriter(w)
|
||||
n = int64(intN)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// WriteFile filename from a a lossless-compressed Bloom Filter f
|
||||
// Suggested file extension: .bf.gz
|
||||
func (f *Filter) WriteFile(filename string) (n int64, err error) {
|
||||
w, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
return f.WriteTo(w)
|
||||
}
|
||||
|
||||
type jsonType struct {
|
||||
Version string `json:"version"`
|
||||
Bits []uint64 `json:"bits"`
|
||||
Keys []uint64 `json:"keys"`
|
||||
M uint64 `json:"m"`
|
||||
N uint64 `json:"n"`
|
||||
}
|
||||
|
||||
func (f *Filter) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&jsonType{
|
||||
string(version),
|
||||
f.bits,
|
||||
f.keys,
|
||||
f.m,
|
||||
f.n,
|
||||
})
|
||||
}
|
||||
|
||||
func (f *Filter) UnmarshalJSON(data []byte) error {
|
||||
var j jsonType
|
||||
if err := json.Unmarshal(data, &j); err != nil {
|
||||
return err
|
||||
}
|
||||
if j.Version != string(version) {
|
||||
return errors.New("incompatible version")
|
||||
}
|
||||
f.bits = j.Bits
|
||||
f.keys = j.Keys
|
||||
f.n = j.N
|
||||
f.m = j.M
|
||||
return nil
|
||||
}
|
||||
|
||||
// GobDecode conforms to interface gob.GobDecoder
|
||||
func (f *Filter) GobDecode(data []byte) error {
|
||||
return f.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
// GobEncode conforms to interface gob.GobEncoder
|
||||
func (f *Filter) GobEncode() ([]byte, error) {
|
||||
return f.MarshalBinary()
|
||||
}
|
||||
35
vendor/github.com/holiman/bloomfilter/v2/iscompatible.go
generated
vendored
Normal file
35
vendor/github.com/holiman/bloomfilter/v2/iscompatible.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
// returns 0 if equal, does not compare len(b0) with len(b1)
|
||||
func noBranchCompareUint64s(b0, b1 []uint64) uint64 {
|
||||
r := uint64(0)
|
||||
for i, b0i := range b0 {
|
||||
r |= b0i ^ b1[i]
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// IsCompatible is true if f and f2 can be Union()ed together
|
||||
func (f *Filter) IsCompatible(f2 *Filter) bool {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
f2.lock.RLock()
|
||||
defer f2.lock.RUnlock()
|
||||
|
||||
// 0 is true, non-0 is false
|
||||
compat := f.M() ^ f2.M()
|
||||
compat |= f.K() ^ f2.K()
|
||||
compat |= noBranchCompareUint64s(f.keys, f2.keys)
|
||||
return compat == 0
|
||||
}
|
||||
117
vendor/github.com/holiman/bloomfilter/v2/new.go
generated
vendored
Normal file
117
vendor/github.com/holiman/bloomfilter/v2/new.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
MMin = 2 // MMin is the minimum Bloom filter bits count
|
||||
KMin = 1 // KMin is the minimum number of keys
|
||||
Uint64Bytes = 8 // Uint64Bytes is the number of bytes in type uint64
|
||||
)
|
||||
|
||||
// OptimalK calculates the optimal k value for creating a new Bloom filter
|
||||
// maxn is the maximum anticipated number of elements
|
||||
func OptimalK(m, maxN uint64) uint64 {
|
||||
return uint64(math.Ceil(float64(m) * math.Ln2 / float64(maxN)))
|
||||
}
|
||||
|
||||
// OptimalM calculates the optimal m value for creating a new Bloom filter
|
||||
// p is the desired false positive probability
|
||||
// optimal m = ceiling( - n * ln(p) / ln(2)**2 )
|
||||
func OptimalM(maxN uint64, p float64) uint64 {
|
||||
return uint64(math.Ceil(-float64(maxN) * math.Log(p) / (math.Ln2 * math.Ln2)))
|
||||
}
|
||||
|
||||
// New Filter with CSPRNG keys
|
||||
//
|
||||
// m is the size of the Bloom filter, in bits, >= 2
|
||||
//
|
||||
// k is the number of random keys, >= 1
|
||||
func New(m, k uint64) (*Filter, error) {
|
||||
return NewWithKeys(m, newRandKeys(m, k))
|
||||
}
|
||||
|
||||
func newRandKeys(m uint64, k uint64) []uint64 {
|
||||
keys := make([]uint64, k)
|
||||
if err := binary.Read(crand.Reader, binary.LittleEndian, keys); err != nil {
|
||||
panic(fmt.Sprintf("Cannot read %d bytes from CSRPNG crypto/rand.Read (err=%v)",
|
||||
Uint64Bytes, err))
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// NewCompatible Filter compatible with f
|
||||
func (f *Filter) NewCompatible() (*Filter, error) {
|
||||
return NewWithKeys(f.m, f.keys)
|
||||
}
|
||||
|
||||
// NewOptimal Bloom filter with random CSPRNG keys
|
||||
func NewOptimal(maxN uint64, p float64) (*Filter, error) {
|
||||
m := OptimalM(maxN, p)
|
||||
k := OptimalK(m, maxN)
|
||||
return New(m, k)
|
||||
}
|
||||
|
||||
// uniqueKeys is true if all keys are unique
|
||||
func uniqueKeys(keys []uint64) bool {
|
||||
for j := 0; j < len(keys)-1; j++ {
|
||||
for i := j + 1; i < len(keys); i++ {
|
||||
if keys[i] == keys[j] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NewWithKeys creates a new Filter from user-supplied origKeys
|
||||
func NewWithKeys(m uint64, origKeys []uint64) (f *Filter, err error) {
|
||||
var (
|
||||
bits []uint64
|
||||
keys []uint64
|
||||
)
|
||||
if bits, err = newBits(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if keys, err = newKeysCopy(origKeys); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Filter{
|
||||
m: m,
|
||||
n: 0,
|
||||
bits: bits,
|
||||
keys: keys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newBits(m uint64) ([]uint64, error) {
|
||||
if m < MMin {
|
||||
return nil, fmt.Errorf("number of bits in the filter must be >= %d (was %d)", MMin, m)
|
||||
}
|
||||
return make([]uint64, (m+63)/64), nil
|
||||
}
|
||||
|
||||
func newKeysCopy(origKeys []uint64) (keys []uint64, err error) {
|
||||
if len(origKeys) < KMin {
|
||||
return nil, fmt.Errorf("keys must have length %d or greater (was %d)", KMin, len(origKeys))
|
||||
}
|
||||
if !uniqueKeys(origKeys) {
|
||||
return nil, fmt.Errorf("Bloom filter keys must be unique")
|
||||
}
|
||||
keys = append(keys, origKeys...)
|
||||
return keys, err
|
||||
}
|
||||
50
vendor/github.com/holiman/bloomfilter/v2/statistics.go
generated
vendored
Normal file
50
vendor/github.com/holiman/bloomfilter/v2/statistics.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Package bloomfilter is face-meltingly fast, thread-safe,
|
||||
// marshalable, unionable, probability- and
|
||||
// optimal-size-calculating Bloom filter in go
|
||||
//
|
||||
// https://github.com/steakknife/bloomfilter
|
||||
//
|
||||
// Copyright © 2014, 2015, 2018 Barry Allard
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// CountBitsUint64s count 1's in b
|
||||
func CountBitsUint64s(b []uint64) int {
|
||||
c := 0
|
||||
for _, x := range b {
|
||||
c += bits.OnesCount64(x)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// PreciseFilledRatio is an exhaustive count # of 1's
|
||||
func (f *Filter) PreciseFilledRatio() float64 {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
return float64(CountBitsUint64s(f.bits)) / float64(f.M())
|
||||
}
|
||||
|
||||
// N is how many elements have been inserted
|
||||
// (actually, how many Add()s have been performed?)
|
||||
func (f *Filter) N() uint64 {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
return f.n
|
||||
}
|
||||
|
||||
// FalsePosititveProbability is the upper-bound probability of false positives
|
||||
// (1 - exp(-k*(n+0.5)/(m-1))) ** k
|
||||
func (f *Filter) FalsePosititveProbability() float64 {
|
||||
k := float64(f.K())
|
||||
n := float64(f.N())
|
||||
m := float64(f.M())
|
||||
return math.Pow(1.0-math.Exp((-k)*(n+0.5)/(m-1)), k)
|
||||
}
|
||||
13
vendor/github.com/holiman/uint256/.deepsource.toml
generated
vendored
Normal file
13
vendor/github.com/holiman/uint256/.deepsource.toml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
version = 1
|
||||
|
||||
test_patterns = [
|
||||
"*/*_test.go",
|
||||
"*_test.go"
|
||||
]
|
||||
|
||||
[[analyzers]]
|
||||
name = "go"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
import_paths = ["github.com/holiman/uint256"]
|
||||
1
vendor/github.com/holiman/uint256/.gitignore
generated
vendored
Normal file
1
vendor/github.com/holiman/uint256/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/.idea
|
||||
7
vendor/github.com/holiman/uint256/AUTHORS
generated
vendored
Normal file
7
vendor/github.com/holiman/uint256/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is the official list of uint256 authors for copyright purposes.
|
||||
|
||||
Martin Holst Swende <martin@swende.se>
|
||||
Guillaume Ballet <gballet@gmail.com>
|
||||
Kurkó Mihály <kurkomisi@users.noreply.github.com>
|
||||
Paweł Bylica <chfast@gmail.com>
|
||||
Yao Zengzeng <yaozengzeng@zju.edu.cn>
|
||||
28
vendor/github.com/holiman/uint256/COPYING
generated
vendored
Normal file
28
vendor/github.com/holiman/uint256/COPYING
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright 2020 uint256 Authors
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
180
vendor/github.com/holiman/uint256/README.md
generated
vendored
Normal file
180
vendor/github.com/holiman/uint256/README.md
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
# Fixed size 256-bit math library
|
||||
|
||||
This is a library specialized at replacing the big.Int library for math based on 256-bit types, used by both
|
||||
[go-ethereum](https://github.com/ethereum/go-ethereum) and [turbo-geth](https://github.com/ledgerwatch/turbo-geth).
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Current benchmarks, with tests ending with `big` being the standard `big.Int` library, and `uint256` being this library.
|
||||
|
||||
### Current status
|
||||
|
||||
- As of 2020-03-18, `uint256` wins over big in every single case, often with orders of magnitude.
|
||||
- And as of release `0.1.0`, the `uint256` library is alloc-free.
|
||||
- With the `1.0.0` release, it also has `100%` test coverage.
|
||||
|
||||
### Conversion from/to `big.Int` and other formats
|
||||
|
||||
```
|
||||
BenchmarkSetFromBig/1word-6 253798280 4.84 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSetFromBig/2words-6 242738034 5.00 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSetFromBig/3words-6 233704105 5.22 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSetFromBig/4words-6 192542544 5.70 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSetFromBig/overflow-6 212680123 6.05 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkToBig/1word-6 14953528 81.6 ns/op 64 B/op 2 allocs/op
|
||||
BenchmarkToBig/2words-6 15932970 85.1 ns/op 64 B/op 2 allocs/op
|
||||
BenchmarkToBig/3words-6 15629001 77.0 ns/op 64 B/op 2 allocs/op
|
||||
BenchmarkToBig/4words-6 14525355 78.0 ns/op 64 B/op 2 allocs/op
|
||||
BenchmarkSetBytes/generic-6 5386718 230 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSetBytes/specific-6 9418405 130 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkRLPEncoding-6 82531 13085 ns/op 11911 B/op 255 allocs/op
|
||||
|
||||
```
|
||||
### Math operations
|
||||
|
||||
`uint256`:
|
||||
```
|
||||
Benchmark_Add/single/uint256-6 575308741 2.19 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Sub/single/uint256-6 551694393 2.71 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Sub/single/uint256_of-6 405466652 2.52 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMul/single/uint256-6 147034321 8.19 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulOverflow/single/uint256-6 45344761 25.4 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSquare/single/uint256-6 196272379 6.14 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Exp/large/uint256-6 374550 3199 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Exp/small/uint256-6 4426760 270 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDiv/small/uint256-6 94629267 12.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDiv/mod64/uint256-6 17367373 67.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDiv/mod128/uint256-6 10192484 130 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDiv/mod192/uint256-6 10936984 107 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDiv/mod256/uint256-6 13436908 93.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMod/small/uint256-6 80138805 15.2 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMod/mod64/uint256-6 17065768 72.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMod/mod128/uint256-6 9469146 123 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMod/mod192/uint256-6 11193145 115 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMod/mod256/uint256-6 12896706 93.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAddMod/small/uint256-6 62187169 21.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAddMod/mod64/uint256-6 15169026 82.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAddMod/mod128/uint256-6 8460835 144 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAddMod/mod192/uint256-6 9273334 141 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAddMod/mod256/uint256-6 10145329 113 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulMod/small/uint256-6 26673195 42.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulMod/mod64/uint256-6 10133446 125 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulMod/mod128/uint256-6 4955551 229 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulMod/mod192/uint256-6 5210977 220 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulMod/mod256/uint256-6 5527972 220 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_SDiv/large/uint256-6 9823093 124 ns/op 0 B/op 0 allocs/op
|
||||
```
|
||||
vs `big.Int`
|
||||
```
|
||||
Benchmark_Add/single/big-6 45798462 25.0 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Sub/single/big-6 51314886 23.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMul/single/big-6 14101502 75.9 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkMulOverflow/single/big-6 15774238 81.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSquare/single/big-6 16739438 71.5 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Exp/large/big-6 41250 42132 ns/op 18144 B/op 189 allocs/op
|
||||
Benchmark_Exp/small/big-6 130993 10813 ns/op 7392 B/op 77 allocs/op
|
||||
BenchmarkDiv/small/big-6 18169453 70.8 ns/op 8 B/op 1 allocs/op
|
||||
BenchmarkDiv/mod64/big-6 7500694 147 ns/op 8 B/op 1 allocs/op
|
||||
BenchmarkDiv/mod128/big-6 3075676 370 ns/op 80 B/op 1 allocs/op
|
||||
BenchmarkDiv/mod192/big-6 3908166 307 ns/op 80 B/op 1 allocs/op
|
||||
BenchmarkDiv/mod256/big-6 4416366 252 ns/op 80 B/op 1 allocs/op
|
||||
BenchmarkMod/small/big-6 19958649 70.8 ns/op 8 B/op 1 allocs/op
|
||||
BenchmarkMod/mod64/big-6 6718828 167 ns/op 64 B/op 1 allocs/op
|
||||
BenchmarkMod/mod128/big-6 3347608 349 ns/op 64 B/op 1 allocs/op
|
||||
BenchmarkMod/mod192/big-6 4072453 293 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkMod/mod256/big-6 4545860 254 ns/op 8 B/op 1 allocs/op
|
||||
BenchmarkAddMod/small/big-6 13976365 79.6 ns/op 8 B/op 1 allocs/op
|
||||
BenchmarkAddMod/mod64/big-6 5799034 208 ns/op 77 B/op 1 allocs/op
|
||||
BenchmarkAddMod/mod128/big-6 2998821 409 ns/op 64 B/op 1 allocs/op
|
||||
BenchmarkAddMod/mod192/big-6 3420640 351 ns/op 61 B/op 1 allocs/op
|
||||
BenchmarkAddMod/mod256/big-6 4124067 298 ns/op 40 B/op 1 allocs/op
|
||||
BenchmarkMulMod/small/big-6 14748193 85.8 ns/op 8 B/op 1 allocs/op
|
||||
BenchmarkMulMod/mod64/big-6 3524833 420 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkMulMod/mod128/big-6 1851936 637 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkMulMod/mod192/big-6 2028134 584 ns/op 80 B/op 1 allocs/op
|
||||
BenchmarkMulMod/mod256/big-6 2125716 576 ns/op 80 B/op 1 allocs/op
|
||||
Benchmark_SDiv/large/big-6 1658139 848 ns/op 312 B/op 6 allocs/op
|
||||
```
|
||||
|
||||
### Boolean logic
|
||||
`uint256`
|
||||
```
|
||||
Benchmark_And/single/uint256-6 571318570 2.13 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Or/single/uint256-6 500672864 2.09 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Xor/single/uint256-6 575198724 2.24 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Cmp/single/uint256-6 400446943 3.09 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkLt/large/uint256-6 322143085 3.50 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkLt/small/uint256-6 351231680 3.33 ns/op 0 B/op 0 allocs/op
|
||||
```
|
||||
vs `big.Int`
|
||||
```
|
||||
Benchmark_And/single/big-6 78524395 16.2 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Or/single/big-6 65390958 20.5 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Xor/single/big-6 58333172 20.6 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Cmp/single/big-6 144781878 8.37 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkLt/large/big-6 95643212 13.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkLt/small/big-6 84561792 14.6 ns/op 0 B/op 0 allocs/op
|
||||
```
|
||||
|
||||
### Bitwise shifts
|
||||
|
||||
`uint256`:
|
||||
```
|
||||
Benchmark_Lsh/n_eq_0/uint256-6 291558974 3.96 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Lsh/n_gt_192/uint256-6 208429646 5.80 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Lsh/n_gt_128/uint256-6 151857447 6.90 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Lsh/n_gt_64/uint256-6 124543732 9.55 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Lsh/n_gt_0/uint256-6 100000000 11.2 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Rsh/n_eq_0/uint256-6 296913555 4.08 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Rsh/n_gt_192/uint256-6 212698939 5.52 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Rsh/n_gt_128/uint256-6 157391629 7.59 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Rsh/n_gt_64/uint256-6 124916373 9.46 ns/op 0 B/op 0 allocs/op
|
||||
Benchmark_Rsh/n_gt_0/uint256-6 100000000 11.5 ns/op
|
||||
```
|
||||
vs `big.Int`:
|
||||
```
|
||||
Benchmark_Lsh/n_eq_0/big-6 21387698 78.6 ns/op 64 B/op 1 allocs/op
|
||||
Benchmark_Lsh/n_gt_192/big-6 15645853 73.9 ns/op 96 B/op 1 allocs/op
|
||||
Benchmark_Lsh/n_gt_128/big-6 15954750 75.0 ns/op 96 B/op 1 allocs/op
|
||||
Benchmark_Lsh/n_gt_64/big-6 16771413 81.3 ns/op 80 B/op 1 allocs/op
|
||||
Benchmark_Lsh/n_gt_0/big-6 17118044 70.7 ns/op 80 B/op 1 allocs/op
|
||||
Benchmark_Rsh/n_eq_0/big-6 21585044 65.5 ns/op 64 B/op 1 allocs/op
|
||||
Benchmark_Rsh/n_gt_192/big-6 28313300 42.3 ns/op 8 B/op 1 allocs/op
|
||||
Benchmark_Rsh/n_gt_128/big-6 21191526 58.1 ns/op 48 B/op 1 allocs/op
|
||||
Benchmark_Rsh/n_gt_64/big-6 15906076 69.0 ns/op 64 B/op 1 allocs/op
|
||||
Benchmark_Rsh/n_gt_0/big-6 19234408 93.0 ns/op 64 B/op 1 allocs/op
|
||||
```
|
||||
## Helping out
|
||||
|
||||
If you're interested in low-level algorithms and/or doing optimizations for shaving off nanoseconds, then this is certainly for you!
|
||||
|
||||
### Implementation work
|
||||
|
||||
Choose an operation, and optimize the s**t out of it!
|
||||
|
||||
A few rules, though, to help your PR get approved:
|
||||
|
||||
- Do not optimize for 'best-case'/'most common case' at the expense of worst-case.
|
||||
- We'll hold off on go assembly for a while, until the algos and interfaces are finished in a 'good enough' first version. After that, it's assembly time.
|
||||
|
||||
### Doing benchmarks
|
||||
|
||||
To do a simple benchmark for everything, do
|
||||
|
||||
```
|
||||
go test -run - -bench . -benchmem
|
||||
|
||||
```
|
||||
|
||||
To see the difference between a branch and master, for a particular benchmark, do
|
||||
|
||||
```
|
||||
git checkout master
|
||||
go test -run - -bench Benchmark_Lsh -benchmem -count=10 > old.txt
|
||||
|
||||
git checkout opt_branch
|
||||
go test -run - -bench Benchmark_Lsh -benchmem -count=10 > new.txt
|
||||
|
||||
benchstat old.txt new.txt
|
||||
|
||||
```
|
||||
107
vendor/github.com/holiman/uint256/circle.yml
generated
vendored
Normal file
107
vendor/github.com/holiman/uint256/circle.yml
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
version: 2.1
|
||||
|
||||
commands:
|
||||
test:
|
||||
parameters:
|
||||
arch:
|
||||
default: "amd64"
|
||||
description: The target architecture.
|
||||
type: enum
|
||||
enum: ["amd64", "386"]
|
||||
steps:
|
||||
- run:
|
||||
name: "Test (<<parameters.arch>>)"
|
||||
command: |
|
||||
export GOARCH=<<parameters.arch>>
|
||||
go version
|
||||
go env
|
||||
go test -v -coverprofile=coverage-<<parameters.arch>>.txt -covermode=count
|
||||
|
||||
jobs:
|
||||
|
||||
go114:
|
||||
docker:
|
||||
- image: cimg/go:1.14
|
||||
steps:
|
||||
- run:
|
||||
name: "Install tools"
|
||||
command: |
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.23.8
|
||||
- checkout
|
||||
- run:
|
||||
name: "Lint"
|
||||
command: golangci-lint run
|
||||
- test:
|
||||
arch: "amd64"
|
||||
- test:
|
||||
arch: "386"
|
||||
- run:
|
||||
name: "Codecov upload"
|
||||
command: bash <(curl -s https://codecov.io/bash)
|
||||
- restore_cache:
|
||||
keys:
|
||||
- corpus
|
||||
- run:
|
||||
name: "Fuzzing"
|
||||
command: |
|
||||
go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
go-fuzz-build
|
||||
timeout --preserve-status --signal INT 1m go-fuzz -procs=2
|
||||
test ! "$(ls crashers)"
|
||||
- save_cache:
|
||||
key: corpus-{{ epoch }}
|
||||
paths:
|
||||
- corpus
|
||||
- run:
|
||||
name: "Benchmark"
|
||||
command: go test -run=- -bench=. -benchmem
|
||||
- run:
|
||||
name: "Build tests for PPC64"
|
||||
command: |
|
||||
GOARCH=ppc64 go test -c
|
||||
mv uint256.test uint256.test.ppc64
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- uint256.test.*
|
||||
|
||||
bigendian:
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:bullseye
|
||||
steps:
|
||||
- run:
|
||||
name: "Install QEMU"
|
||||
command: sudo apt-get -q update && sudo apt-get -qy install qemu-user-static --no-install-recommends
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: "Test (PPC64 emulation)"
|
||||
command: qemu-ppc64-static uint256.test.ppc64 -test.v
|
||||
|
||||
|
||||
go113:
|
||||
docker:
|
||||
- image: cimg/go:1.13
|
||||
steps:
|
||||
- checkout
|
||||
- test
|
||||
|
||||
go112:
|
||||
docker:
|
||||
- image: cimg/go:1.12
|
||||
steps:
|
||||
- checkout
|
||||
- test
|
||||
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
uint256:
|
||||
jobs:
|
||||
- go114
|
||||
- go113
|
||||
- go112
|
||||
- bigendian:
|
||||
requires:
|
||||
- go114
|
||||
10
vendor/github.com/holiman/uint256/codecov.yml
generated
vendored
Normal file
10
vendor/github.com/holiman/uint256/codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
codecov:
|
||||
require_ci_to_pass: no
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project: no
|
||||
patch: no
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
||||
554
vendor/github.com/holiman/uint256/conversion.go
generated
vendored
Normal file
554
vendor/github.com/holiman/uint256/conversion.go
generated
vendored
Normal file
@@ -0,0 +1,554 @@
|
||||
// uint256: Fixed size 256-bit math library
|
||||
// Copyright 2020 uint256 Authors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package uint256
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
const (
|
||||
maxWords = 256 / bits.UintSize // number of big.Words in 256-bit
|
||||
|
||||
// The constants below work as compile-time checks: in case evaluated to
|
||||
// negative value it cannot be assigned to uint type and compilation fails.
|
||||
// These particular expressions check if maxWords either 4 or 8 matching
|
||||
// 32-bit and 64-bit architectures.
|
||||
_ uint = -(maxWords & (maxWords - 1)) // maxWords is power of two.
|
||||
_ uint = -(maxWords & ^(4 | 8)) // maxWords is 4 or 8.
|
||||
)
|
||||
|
||||
// ToBig returns a big.Int version of z.
|
||||
func (z *Int) ToBig() *big.Int {
|
||||
b := new(big.Int)
|
||||
switch maxWords { // Compile-time check.
|
||||
case 4: // 64-bit architectures.
|
||||
words := [4]big.Word{big.Word(z[0]), big.Word(z[1]), big.Word(z[2]), big.Word(z[3])}
|
||||
b.SetBits(words[:])
|
||||
case 8: // 32-bit architectures.
|
||||
words := [8]big.Word{
|
||||
big.Word(z[0]), big.Word(z[0] >> 32),
|
||||
big.Word(z[1]), big.Word(z[1] >> 32),
|
||||
big.Word(z[2]), big.Word(z[2] >> 32),
|
||||
big.Word(z[3]), big.Word(z[3] >> 32),
|
||||
}
|
||||
b.SetBits(words[:])
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// FromBig is a convenience-constructor from big.Int.
|
||||
// Returns a new Int and whether overflow occurred.
|
||||
func FromBig(b *big.Int) (*Int, bool) {
|
||||
z := &Int{}
|
||||
overflow := z.SetFromBig(b)
|
||||
return z, overflow
|
||||
}
|
||||
|
||||
// fromHex is the internal implementation of parsing a hex-string.
|
||||
func (z *Int) fromHex(hex string) error {
|
||||
if err := checkNumberS(hex); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(hex) > 66 {
|
||||
return ErrBig256Range
|
||||
}
|
||||
end := len(hex)
|
||||
for i := 0; i < 4; i++ {
|
||||
start := end - 16
|
||||
if start < 2 {
|
||||
start = 2
|
||||
}
|
||||
for ri := start; ri < end; ri++ {
|
||||
nib := bintable[hex[ri]]
|
||||
if nib == badNibble {
|
||||
return ErrSyntax
|
||||
}
|
||||
z[i] = z[i] << 4
|
||||
z[i] += uint64(nib)
|
||||
}
|
||||
end = start
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FromHex is a convenience-constructor to create an Int from
|
||||
// a hexadecimal string. The string is required to be '0x'-prefixed
|
||||
// Numbers larger than 256 bits are not accepted.
|
||||
func FromHex(hex string) (*Int, error) {
|
||||
var z Int
|
||||
if err := z.fromHex(hex); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &z, nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler
|
||||
func (z *Int) UnmarshalText(input []byte) error {
|
||||
return z.fromHex(string(input))
|
||||
}
|
||||
|
||||
// SetFromBig converts a big.Int to Int and sets the value to z.
|
||||
// TODO: Ensure we have sufficient testing, esp for negative bigints.
|
||||
func (z *Int) SetFromBig(b *big.Int) bool {
|
||||
z.Clear()
|
||||
words := b.Bits()
|
||||
overflow := len(words) > maxWords
|
||||
|
||||
switch maxWords { // Compile-time check.
|
||||
case 4: // 64-bit architectures.
|
||||
if len(words) > 0 {
|
||||
z[0] = uint64(words[0])
|
||||
if len(words) > 1 {
|
||||
z[1] = uint64(words[1])
|
||||
if len(words) > 2 {
|
||||
z[2] = uint64(words[2])
|
||||
if len(words) > 3 {
|
||||
z[3] = uint64(words[3])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case 8: // 32-bit architectures.
|
||||
numWords := len(words)
|
||||
if overflow {
|
||||
numWords = maxWords
|
||||
}
|
||||
for i := 0; i < numWords; i++ {
|
||||
if i%2 == 0 {
|
||||
z[i/2] = uint64(words[i])
|
||||
} else {
|
||||
z[i/2] |= uint64(words[i]) << 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if b.Sign() == -1 {
|
||||
z.Neg(z)
|
||||
}
|
||||
return overflow
|
||||
}
|
||||
|
||||
// Format implements fmt.Formatter. It accepts the formats
|
||||
// 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix),
|
||||
// 'd' (decimal), 'x' (lowercase hexadecimal), and
|
||||
// 'X' (uppercase hexadecimal).
|
||||
// Also supported are the full suite of package fmt's format
|
||||
// flags for integral types, including '+' and ' ' for sign
|
||||
// control, '#' for leading zero in octal and for hexadecimal,
|
||||
// a leading "0x" or "0X" for "%#x" and "%#X" respectively,
|
||||
// specification of minimum digits precision, output field
|
||||
// width, space or zero padding, and '-' for left or right
|
||||
// justification.
|
||||
//
|
||||
func (z *Int) Format(s fmt.State, ch rune) {
|
||||
z.ToBig().Format(s, ch)
|
||||
}
|
||||
|
||||
// SetBytes8 is identical to SetBytes(in[:8]), but panics is input is too short
|
||||
func (z *Int) SetBytes8(in []byte) *Int {
|
||||
_ = in[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = binary.BigEndian.Uint64(in[0:8])
|
||||
return z
|
||||
}
|
||||
|
||||
// SetBytes16 is identical to SetBytes(in[:16]), but panics is input is too short
|
||||
func (z *Int) SetBytes16(in []byte) *Int {
|
||||
_ = in[15] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = binary.BigEndian.Uint64(in[0:8])
|
||||
z[0] = binary.BigEndian.Uint64(in[8:16])
|
||||
return z
|
||||
}
|
||||
|
||||
// SetBytes16 is identical to SetBytes(in[:24]), but panics is input is too short
|
||||
func (z *Int) SetBytes24(in []byte) *Int {
|
||||
_ = in[23] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = binary.BigEndian.Uint64(in[0:8])
|
||||
z[1] = binary.BigEndian.Uint64(in[8:16])
|
||||
z[0] = binary.BigEndian.Uint64(in[16:24])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes32(in []byte) *Int {
|
||||
_ = in[31] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = binary.BigEndian.Uint64(in[0:8])
|
||||
z[2] = binary.BigEndian.Uint64(in[8:16])
|
||||
z[1] = binary.BigEndian.Uint64(in[16:24])
|
||||
z[0] = binary.BigEndian.Uint64(in[24:32])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes1(in []byte) *Int {
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = uint64(in[0])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes9(in []byte) *Int {
|
||||
_ = in[8] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = uint64(in[0])
|
||||
z[0] = binary.BigEndian.Uint64(in[1:9])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes17(in []byte) *Int {
|
||||
_ = in[16] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = uint64(in[0])
|
||||
z[1] = binary.BigEndian.Uint64(in[1:9])
|
||||
z[0] = binary.BigEndian.Uint64(in[9:17])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes25(in []byte) *Int {
|
||||
_ = in[24] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = uint64(in[0])
|
||||
z[2] = binary.BigEndian.Uint64(in[1:9])
|
||||
z[1] = binary.BigEndian.Uint64(in[9:17])
|
||||
z[0] = binary.BigEndian.Uint64(in[17:25])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes2(in []byte) *Int {
|
||||
_ = in[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = uint64(binary.BigEndian.Uint16(in[0:2]))
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes10(in []byte) *Int {
|
||||
_ = in[9] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = uint64(binary.BigEndian.Uint16(in[0:2]))
|
||||
z[0] = binary.BigEndian.Uint64(in[2:10])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes18(in []byte) *Int {
|
||||
_ = in[17] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = uint64(binary.BigEndian.Uint16(in[0:2]))
|
||||
z[1] = binary.BigEndian.Uint64(in[2:10])
|
||||
z[0] = binary.BigEndian.Uint64(in[10:18])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes26(in []byte) *Int {
|
||||
_ = in[25] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = uint64(binary.BigEndian.Uint16(in[0:2]))
|
||||
z[2] = binary.BigEndian.Uint64(in[2:10])
|
||||
z[1] = binary.BigEndian.Uint64(in[10:18])
|
||||
z[0] = binary.BigEndian.Uint64(in[18:26])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes3(in []byte) *Int {
|
||||
_ = in[2] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes11(in []byte) *Int {
|
||||
_ = in[10] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
|
||||
z[0] = binary.BigEndian.Uint64(in[3:11])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes19(in []byte) *Int {
|
||||
_ = in[18] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
|
||||
z[1] = binary.BigEndian.Uint64(in[3:11])
|
||||
z[0] = binary.BigEndian.Uint64(in[11:19])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes27(in []byte) *Int {
|
||||
_ = in[26] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
|
||||
z[2] = binary.BigEndian.Uint64(in[3:11])
|
||||
z[1] = binary.BigEndian.Uint64(in[11:19])
|
||||
z[0] = binary.BigEndian.Uint64(in[19:27])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes4(in []byte) *Int {
|
||||
_ = in[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = uint64(binary.BigEndian.Uint32(in[0:4]))
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes12(in []byte) *Int {
|
||||
_ = in[11] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = uint64(binary.BigEndian.Uint32(in[0:4]))
|
||||
z[0] = binary.BigEndian.Uint64(in[4:12])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes20(in []byte) *Int {
|
||||
_ = in[19] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = uint64(binary.BigEndian.Uint32(in[0:4]))
|
||||
z[1] = binary.BigEndian.Uint64(in[4:12])
|
||||
z[0] = binary.BigEndian.Uint64(in[12:20])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes28(in []byte) *Int {
|
||||
_ = in[27] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = uint64(binary.BigEndian.Uint32(in[0:4]))
|
||||
z[2] = binary.BigEndian.Uint64(in[4:12])
|
||||
z[1] = binary.BigEndian.Uint64(in[12:20])
|
||||
z[0] = binary.BigEndian.Uint64(in[20:28])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes5(in []byte) *Int {
|
||||
_ = in[4] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = bigEndianUint40(in[0:5])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes13(in []byte) *Int {
|
||||
_ = in[12] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = bigEndianUint40(in[0:5])
|
||||
z[0] = binary.BigEndian.Uint64(in[5:13])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes21(in []byte) *Int {
|
||||
_ = in[20] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = bigEndianUint40(in[0:5])
|
||||
z[1] = binary.BigEndian.Uint64(in[5:13])
|
||||
z[0] = binary.BigEndian.Uint64(in[13:21])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes29(in []byte) *Int {
|
||||
_ = in[23] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = bigEndianUint40(in[0:5])
|
||||
z[2] = binary.BigEndian.Uint64(in[5:13])
|
||||
z[1] = binary.BigEndian.Uint64(in[13:21])
|
||||
z[0] = binary.BigEndian.Uint64(in[21:29])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes6(in []byte) *Int {
|
||||
_ = in[5] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = bigEndianUint48(in[0:6])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes14(in []byte) *Int {
|
||||
_ = in[13] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = bigEndianUint48(in[0:6])
|
||||
z[0] = binary.BigEndian.Uint64(in[6:14])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes22(in []byte) *Int {
|
||||
_ = in[21] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = bigEndianUint48(in[0:6])
|
||||
z[1] = binary.BigEndian.Uint64(in[6:14])
|
||||
z[0] = binary.BigEndian.Uint64(in[14:22])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes30(in []byte) *Int {
|
||||
_ = in[29] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = bigEndianUint48(in[0:6])
|
||||
z[2] = binary.BigEndian.Uint64(in[6:14])
|
||||
z[1] = binary.BigEndian.Uint64(in[14:22])
|
||||
z[0] = binary.BigEndian.Uint64(in[22:30])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes7(in []byte) *Int {
|
||||
_ = in[6] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2], z[1] = 0, 0, 0
|
||||
z[0] = bigEndianUint56(in[0:7])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes15(in []byte) *Int {
|
||||
_ = in[14] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3], z[2] = 0, 0
|
||||
z[1] = bigEndianUint56(in[0:7])
|
||||
z[0] = binary.BigEndian.Uint64(in[7:15])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes23(in []byte) *Int {
|
||||
_ = in[22] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = 0
|
||||
z[2] = bigEndianUint56(in[0:7])
|
||||
z[1] = binary.BigEndian.Uint64(in[7:15])
|
||||
z[0] = binary.BigEndian.Uint64(in[15:23])
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) SetBytes31(in []byte) *Int {
|
||||
_ = in[30] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
z[3] = bigEndianUint56(in[0:7])
|
||||
z[2] = binary.BigEndian.Uint64(in[7:15])
|
||||
z[1] = binary.BigEndian.Uint64(in[15:23])
|
||||
z[0] = binary.BigEndian.Uint64(in[23:31])
|
||||
return z
|
||||
}
|
||||
|
||||
// Utility methods that are "missing" among the bigEndian.UintXX methods.
|
||||
|
||||
func bigEndianUint40(b []byte) uint64 {
|
||||
_ = b[4] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | uint64(b[1])<<24 |
|
||||
uint64(b[0])<<32
|
||||
}
|
||||
|
||||
func bigEndianUint48(b []byte) uint64 {
|
||||
_ = b[5] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | uint64(b[2])<<24 |
|
||||
uint64(b[1])<<32 | uint64(b[0])<<40
|
||||
}
|
||||
|
||||
func bigEndianUint56(b []byte) uint64 {
|
||||
_ = b[6] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[6]) | uint64(b[5])<<8 | uint64(b[4])<<16 | uint64(b[3])<<24 |
|
||||
uint64(b[2])<<32 | uint64(b[1])<<40 | uint64(b[0])<<48
|
||||
}
|
||||
|
||||
// EncodeRLP implements the rlp.Encoder interface from go-ethereum
|
||||
// and writes the RLP encoding of z to w.
|
||||
func (z *Int) EncodeRLP(w io.Writer) error {
|
||||
if z == nil {
|
||||
_, err := w.Write([]byte{0x80})
|
||||
return err
|
||||
}
|
||||
nBits := z.BitLen()
|
||||
if nBits == 0 {
|
||||
_, err := w.Write([]byte{0x80})
|
||||
return err
|
||||
}
|
||||
if nBits <= 7 {
|
||||
_, err := w.Write([]byte{byte(z[0])})
|
||||
return err
|
||||
}
|
||||
nBytes := byte((nBits + 7) / 8)
|
||||
var b [33]byte
|
||||
binary.BigEndian.PutUint64(b[1:9], z[3])
|
||||
binary.BigEndian.PutUint64(b[9:17], z[2])
|
||||
binary.BigEndian.PutUint64(b[17:25], z[1])
|
||||
binary.BigEndian.PutUint64(b[25:33], z[0])
|
||||
b[32-nBytes] = 0x80 + nBytes
|
||||
_, err := w.Write(b[32-nBytes:])
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler
|
||||
func (z *Int) MarshalText() ([]byte, error) {
|
||||
return []byte(z.Hex()), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (z *Int) UnmarshalJSON(input []byte) error {
|
||||
if len(input) < 2 || input[0] != '"' || input[len(input)-1] != '"' {
|
||||
return ErrNonString
|
||||
}
|
||||
return z.UnmarshalText(input[1 : len(input)-1])
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (z *Int) String() string {
|
||||
return z.Hex()
|
||||
}
|
||||
|
||||
const (
|
||||
hextable = "0123456789abcdef"
|
||||
bintable = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x01\x02\x03\x04\x05\x06\a\b\t\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
badNibble = 0xff
|
||||
)
|
||||
|
||||
// Hex encodes z in 0x-prefixed hexadecimal form.
|
||||
func (z *Int) Hex() string {
|
||||
// This implementation is not optimal, it allocates a full
|
||||
// 66-byte output buffer which it fills. It could instead allocate a smaller
|
||||
// buffer, and omit the final crop-stage.
|
||||
output := make([]byte, 66)
|
||||
nibbles := (z.BitLen() + 3) / 4 // nibbles [0,64]
|
||||
if nibbles == 0 {
|
||||
nibbles = 1
|
||||
}
|
||||
// Start with the most significant
|
||||
zWord := (nibbles - 1) / 16
|
||||
for i := zWord; i >= 0; i-- {
|
||||
off := (3 - i) * 16
|
||||
output[off+2] = hextable[byte(z[i]>>60)&0xf]
|
||||
output[off+3] = hextable[byte(z[i]>>56)&0xf]
|
||||
output[off+4] = hextable[byte(z[i]>>52)&0xf]
|
||||
output[off+5] = hextable[byte(z[i]>>48)&0xf]
|
||||
output[off+6] = hextable[byte(z[i]>>44)&0xf]
|
||||
output[off+7] = hextable[byte(z[i]>>40)&0xf]
|
||||
output[off+8] = hextable[byte(z[i]>>36)&0xf]
|
||||
output[off+9] = hextable[byte(z[i]>>32)&0xf]
|
||||
output[off+10] = hextable[byte(z[i]>>28)&0xf]
|
||||
output[off+11] = hextable[byte(z[i]>>24)&0xf]
|
||||
output[off+12] = hextable[byte(z[i]>>20)&0xf]
|
||||
output[off+13] = hextable[byte(z[i]>>16)&0xf]
|
||||
output[off+14] = hextable[byte(z[i]>>12)&0xf]
|
||||
output[off+15] = hextable[byte(z[i]>>8)&0xf]
|
||||
output[off+16] = hextable[byte(z[i]>>4)&0xf]
|
||||
output[off+17] = hextable[byte(z[i]&0xF)&0xf]
|
||||
}
|
||||
output[64-nibbles] = '0'
|
||||
output[65-nibbles] = 'x'
|
||||
return string(output[64-nibbles:])
|
||||
}
|
||||
|
||||
var (
|
||||
ErrEmptyString = errors.New("empty hex string")
|
||||
ErrSyntax = errors.New("invalid hex string")
|
||||
ErrMissingPrefix = errors.New("hex string without 0x prefix")
|
||||
ErrEmptyNumber = errors.New("hex string \"0x\"")
|
||||
ErrLeadingZero = errors.New("hex number with leading zero digits")
|
||||
ErrBig256Range = errors.New("hex number > 256 bits")
|
||||
ErrNonString = errors.New("non-string")
|
||||
)
|
||||
|
||||
func checkNumberS(input string) error {
|
||||
l := len(input)
|
||||
if l == 0 {
|
||||
return ErrEmptyString
|
||||
}
|
||||
if l < 2 || input[0] != '0' ||
|
||||
(input[1] != 'x' && input[1] != 'X') {
|
||||
return ErrMissingPrefix
|
||||
}
|
||||
if l == 2 {
|
||||
return ErrEmptyNumber
|
||||
}
|
||||
if len(input) > 3 && input[2] == '0' {
|
||||
return ErrLeadingZero
|
||||
}
|
||||
return nil
|
||||
}
|
||||
38
vendor/github.com/holiman/uint256/div.go
generated
vendored
Normal file
38
vendor/github.com/holiman/uint256/div.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// uint256: Fixed size 256-bit math library
|
||||
// Copyright 2020 uint256 Authors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package uint256
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// reciprocal2by1 computes <^d, ^0> / d.
|
||||
func reciprocal2by1(d uint64) uint64 {
|
||||
reciprocal, _ := bits.Div64(^d, ^uint64(0), d)
|
||||
return reciprocal
|
||||
}
|
||||
|
||||
// udivrem2by1 divides <uh, ul> / d and produces both quotient and remainder.
|
||||
// It uses the provided d's reciprocal.
|
||||
// Implementation ported from https://github.com/chfast/intx and is based on
|
||||
// "Improved division by invariant integers", Algorithm 4.
|
||||
func udivrem2by1(uh, ul, d, reciprocal uint64) (quot, rem uint64) {
|
||||
qh, ql := bits.Mul64(reciprocal, uh)
|
||||
ql, carry := bits.Add64(ql, ul, 0)
|
||||
qh, _ = bits.Add64(qh, uh, carry)
|
||||
qh++
|
||||
|
||||
r := ul - qh*d
|
||||
|
||||
if r > ql {
|
||||
qh--
|
||||
r += d
|
||||
}
|
||||
|
||||
if r >= d {
|
||||
qh++
|
||||
r -= d
|
||||
}
|
||||
|
||||
return qh, r
|
||||
}
|
||||
133
vendor/github.com/holiman/uint256/fuzz.go
generated
vendored
Normal file
133
vendor/github.com/holiman/uint256/fuzz.go
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// uint256: Fixed size 256-bit math library
|
||||
// Copyright 2020 uint256 Authors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// +build gofuzz
|
||||
|
||||
package uint256
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
opUdivrem = 0
|
||||
opMul = 1
|
||||
opLsh = 2
|
||||
opAdd = 4
|
||||
opSub = 5
|
||||
)
|
||||
|
||||
type opFunc func(*Int, *Int, *Int) *Int
|
||||
type bigFunc func(*big.Int, *big.Int, *big.Int) *big.Int
|
||||
|
||||
func crash(op opFunc, x, y Int, msg string) {
|
||||
fn := runtime.FuncForPC(reflect.ValueOf(op).Pointer())
|
||||
fnName := fn.Name()
|
||||
fnFile, fnLine := fn.FileLine(fn.Entry())
|
||||
panic(fmt.Sprintf("%s\nfor %s (%s:%d)\nx: %x\ny: %x", msg, fnName, fnFile, fnLine, &x, &y))
|
||||
}
|
||||
|
||||
func checkOp(op opFunc, bigOp bigFunc, x, y Int) {
|
||||
origX := x
|
||||
origY := y
|
||||
|
||||
var result Int
|
||||
ret := op(&result, &x, &y)
|
||||
if ret != &result {
|
||||
crash(op, x, y, "returned not the pointer receiver")
|
||||
}
|
||||
if x != origX {
|
||||
crash(op, x, y, "first argument modified")
|
||||
}
|
||||
if y != origY {
|
||||
crash(op, x, y, "second argument modified")
|
||||
}
|
||||
|
||||
expected, _ := FromBig(bigOp(new(big.Int), x.ToBig(), y.ToBig()))
|
||||
if result != *expected {
|
||||
crash(op, x, y, "unexpected result")
|
||||
}
|
||||
|
||||
// Test again when the receiver is not zero.
|
||||
var garbage Int
|
||||
garbage.Xor(&x, &y)
|
||||
ret = op(&garbage, &x, &y)
|
||||
if ret != &garbage {
|
||||
crash(op, x, y, "returned not the pointer receiver")
|
||||
}
|
||||
if garbage != *expected {
|
||||
crash(op, x, y, "unexpected result")
|
||||
}
|
||||
if x != origX {
|
||||
crash(op, x, y, "first argument modified")
|
||||
}
|
||||
if y != origY {
|
||||
crash(op, x, y, "second argument modified")
|
||||
}
|
||||
|
||||
// Test again with the receiver aliasing arguments.
|
||||
ret = op(&x, &x, &y)
|
||||
if ret != &x {
|
||||
crash(op, x, y, "returned not the pointer receiver")
|
||||
}
|
||||
if x != *expected {
|
||||
crash(op, x, y, "unexpected result")
|
||||
}
|
||||
|
||||
ret = op(&y, &origX, &y)
|
||||
if ret != &y {
|
||||
crash(op, x, y, "returned not the pointer receiver")
|
||||
}
|
||||
if y != *expected {
|
||||
crash(op, x, y, "unexpected result")
|
||||
}
|
||||
}
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
if len(data) != 65 {
|
||||
return 0
|
||||
}
|
||||
|
||||
op := data[0]
|
||||
|
||||
var x, y Int
|
||||
x.SetBytes(data[1:33])
|
||||
y.SetBytes(data[33:])
|
||||
|
||||
switch op {
|
||||
case opUdivrem:
|
||||
if y.IsZero() {
|
||||
return 0
|
||||
}
|
||||
checkOp((*Int).Div, (*big.Int).Div, x, y)
|
||||
checkOp((*Int).Mod, (*big.Int).Mod, x, y)
|
||||
|
||||
case opMul:
|
||||
checkOp((*Int).Mul, (*big.Int).Mul, x, y)
|
||||
|
||||
case opLsh:
|
||||
lsh := func(z, x, y *Int) *Int {
|
||||
return z.Lsh(x, uint(y[0]))
|
||||
}
|
||||
bigLsh := func(z, x, y *big.Int) *big.Int {
|
||||
n := uint(y.Uint64())
|
||||
if n > 256 {
|
||||
n = 256
|
||||
}
|
||||
return z.Lsh(x, n)
|
||||
}
|
||||
checkOp(lsh, bigLsh, x, y)
|
||||
|
||||
case opAdd:
|
||||
checkOp((*Int).Add, (*big.Int).Add, x, y)
|
||||
|
||||
case opSub:
|
||||
checkOp((*Int).Sub, (*big.Int).Sub, x, y)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
1134
vendor/github.com/holiman/uint256/uint256.go
generated
vendored
Normal file
1134
vendor/github.com/holiman/uint256/uint256.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user