status-go/vendor/github.com/multiformats/go-varint/varint.go

95 lines
2.4 KiB
Go
Raw Normal View History

Feature/key compression (#1990) ## What has changed? I've introduced to the public binding functionality that will compress and decompress public keys of a variety of encoding and key types. This functionality supports all major byte encoding formats and the following EC public key types: - `secp256k1` pks - `bls12-381 g1` pks - `bls12-381 g2` pks ## Why make the change? We want shorter public (chat) keys and we want to be future proof and encoding agnostic. See the issue here https://github.com/status-im/status-go/issues/1937 --- * Added basic signature for compresspk and uncompresspk * Added basic encoding information * make vendor * formatted imports for the linter * Reformatted imports hoping linter likes it * This linter is capricious * Added check that the secp256k1 key is valid * Added test for valid key * Added multiformat/go-varint dep * Added public key type handling * Added key decompression with key type handling * Added handling for '0x' type indentifying * Added more robust testing * Less lint for the linting gods * make vendor for bls12_381 * Added bls12-381 compression tests * Added decompress key expected results * Refactor of typed and untyped keys in tests * Lint god appeasment * Refactor of sample public keys * Implemented bls12-381 decompression * gofmt * Renamed decode/encode funcs to be more descriptive * Added binary bindings for key de/compression * Refactor of func parameters gomobile is a bit tempermental using raw bytes as a parameter, so I've decided to use string only inputs and outputs * gofmt * Added function documentation * Moved multiformat de/compression into api/multiformat ns * Moved multiformat de/compression into api/multiformat ns * Changed compress to serialize on API
2020-06-23 10:47:17 +00:00
package varint
import (
"encoding/binary"
"errors"
"io"
"math/bits"
)
var (
ErrOverflow = errors.New("varints larger than uint64 not yet supported")
ErrUnderflow = errors.New("varints malformed, could not reach the end")
ErrNotMinimal = errors.New("varint not minimally encoded")
)
// UvarintSize returns the size (in bytes) of `num` encoded as a unsigned varint.
func UvarintSize(num uint64) int {
bits := bits.Len64(num)
q, r := bits/7, bits%7
size := q
if r > 0 || size == 0 {
size++
}
return size
}
// ToUvarint converts an unsigned integer to a varint-encoded []byte
func ToUvarint(num uint64) []byte {
buf := make([]byte, UvarintSize(num))
n := binary.PutUvarint(buf, uint64(num))
return buf[:n]
}
// FromUvarint reads an unsigned varint from the beginning of buf, returns the
// varint, and the number of bytes read.
func FromUvarint(buf []byte) (uint64, int, error) {
// Modified from the go standard library. Copyright the Go Authors and
// released under the BSD License.
var x uint64
var s uint
for i, b := range buf {
if b < 0x80 {
if i > 9 || i == 9 && b > 1 {
return 0, 0, ErrOverflow
} else if b == 0 && s > 0 {
return 0, 0, ErrNotMinimal
}
return x | uint64(b)<<s, i + 1, nil
}
x |= uint64(b&0x7f) << s
s += 7
}
return 0, 0, ErrUnderflow
}
// ReadUvarint reads a unsigned varint from the given reader.
func ReadUvarint(r io.ByteReader) (uint64, error) {
// Modified from the go standard library. Copyright the Go Authors and
// released under the BSD License.
var x uint64
var s uint
for i := 0; ; i++ {
b, err := r.ReadByte()
if err != nil {
if err == io.EOF && i != 0 {
// "eof" will look like a success.
// If we've read part of a value, this is not a
// success.
err = io.ErrUnexpectedEOF
}
return 0, err
}
if b < 0x80 {
if i > 9 || i == 9 && b > 1 {
return 0, ErrOverflow
} else if b == 0 && s > 0 {
// we should never _finish_ on a 0 byte if we
// have more than one byte.
return 0, ErrNotMinimal
}
return x | uint64(b)<<s, nil
}
x |= uint64(b&0x7f) << s
s += 7
}
}
// PutUvarint is an alias for binary.PutUvarint.
//
// This is provided for convenience so users of this library can avoid built-in
// varint functions and easily audit code for uses of those functions.
func PutUvarint(buf []byte, x uint64) int {
return binary.PutUvarint(buf, x)
}