func (f *Filter) Bytes() ([]byte, error) {
	filterData := make([]byte, len(f.filterData))
	copy(filterData, f.filterData)
	return filterData, nil
}
Bytes returns the serialized format of the GCS filter, which does not
include N or P (returned by separate methods) or the key used by SipHash.
package gcs
import (
	"bytes"
	"fmt"
	"io"
	"sort"
	"github.com/aead/siphash"
	"github.com/soteria-dag/soterd/wire"
	"github.com/kkdai/bstream"
)
var (
	ErrNTooBig = fmt.Errorf("N is too big to fit in uint32")
	ErrPTooBig = fmt.Errorf("P is too big to fit in uint32")
)
const (
	KeySize = 16
	varIntProtoVer uint32 = 0
)
func fastReduction(v, nHi, nLo uint64) uint64 {
	vhi := v >> 32
	vlo := uint64(uint32(v))
	vnphi := vhi * nHi
	vnpmid := vhi * nLo
	npvmid := nHi * vlo
	vnplo := vlo * nLo
	carry := (uint64(uint32(vnpmid)) + uint64(uint32(npvmid)) +
		(vnplo >> 32)) >> 32
	v = vnphi + (vnpmid >> 32) + (npvmid >> 32) + carry
	return v
}
type Filter struct {
	n         uint32
	p         uint8
	modulusNP uint64
	filterData []byte
}
func BuildGCSFilter(P uint8, M uint64, key [KeySize]byte, data [][]byte) (*Filter, error) {
	if uint64(len(data)) >= (1 << 32) {
		return nil, ErrNTooBig
	}
	if P > 32 {
		return nil, ErrPTooBig
	}
	f := Filter{
		n: uint32(len(data)),
		p: P,
	}
	f.modulusNP = uint64(f.n) * M
	if f.n == 0 {
		return &f, nil
	}
	values := make(uint64Slice, 0, len(data))
	b := bstream.NewBStreamWriter(0)
	nphi := f.modulusNP >> 32
	nplo := uint64(uint32(f.modulusNP))
	for _, d := range data {
		v := siphash.Sum64(d, &key)
		v = fastReduction(v, nphi, nplo)
		values = append(values, v)
	}
	sort.Sort(values)
	var value, lastValue, remainder uint64
	for _, v := range values {
		remainder = (v - lastValue) & ((uint64(1) << f.p) - 1)
		value = (v - lastValue - remainder) >> f.p
		lastValue = v
		for value > 0 {
			b.WriteBit(true)
			value--
		}
		b.WriteBit(false)
		b.WriteBits(remainder, int(f.p))
	}
	f.filterData = b.Bytes()
	return &f, nil
}
func FromBytes(N uint32, P uint8, M uint64, d []byte) (*Filter, error) {
	if P > 32 {
		return nil, ErrPTooBig
	}
	f := &Filter{
		n: N,
		p: P,
	}
	f.modulusNP = uint64(f.n) * M
	f.filterData = make([]byte, len(d))
	copy(f.filterData, d)
	return f, nil
}
func FromNBytes(P uint8, M uint64, d []byte) (*Filter, error) {
	buffer := bytes.NewBuffer(d)
	N, err := wire.ReadVarInt(buffer, varIntProtoVer)
	if err != nil {
		return nil, err
	}
	if N >= (1 << 32) {
		return nil, ErrNTooBig
	}
	return FromBytes(uint32(N), P, M, buffer.Bytes())
}