1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package derive
import (
"bytes"
"fmt"
"io"
"math/big"
)
// decodeSpanBatchBits decodes a standard span-batch bitlist.
// The bitlist is encoded as big-endian integer, left-padded with zeroes to a multiple of 8 bits.
// The encoded bitlist cannot be longer than MaxSpanBatchSize.
func decodeSpanBatchBits(r *bytes.Reader, bitLength uint64) (*big.Int, error) {
// Round up, ensure enough bytes when number of bits is not a multiple of 8.
// Alternative of (L+7)/8 is not overflow-safe.
bufLen := bitLength / 8
if bitLength%8 != 0 {
bufLen++
}
buf := make([]byte, bufLen)
_, err := io.ReadFull(r, buf)
if err != nil {
return nil, fmt.Errorf("failed to read bits: %w", err)
}
out := new(big.Int)
out.SetBytes(buf)
// We read the correct number of bytes, but there may still be trailing bits
if l := uint64(out.BitLen()); l > bitLength {
return nil, fmt.Errorf("bitfield has %d bits, but expected no more than %d", l, bitLength)
}
return out, nil
}
// encodeSpanBatchBits encodes a standard span-batch bitlist.
// The bitlist is encoded as big-endian integer, left-padded with zeroes to a multiple of 8 bits.
// The encoded bitlist cannot be longer than MaxSpanBatchSize.
func encodeSpanBatchBits(w io.Writer, bitLength uint64, bits *big.Int) error {
if l := uint64(bits.BitLen()); l > bitLength {
return fmt.Errorf("bitfield is larger than bitLength: %d > %d", l, bitLength)
}
// Round up, ensure enough bytes when number of bits is not a multiple of 8.
// Alternative of (L+7)/8 is not overflow-safe.
bufLen := bitLength / 8
if bitLength%8 != 0 { // rounding up this way is safe against overflows
bufLen++
}
buf := make([]byte, bufLen)
bits.FillBytes(buf) // zero-extended, big-endian
if _, err := w.Write(buf); err != nil {
return fmt.Errorf("cannot write bits: %w", err)
}
return nil
}