mirror of
https://github.com/luxfi/kms.git
synced 2026-07-27 03:38:31 +00:00
ghcr.io/luxfi/kms-operator has had no new image since v1.12.3. The Build KMS
Operator workflow failed on every tag since (v1.12.4 … v1.12.7) while its
sibling Build KMS succeeded on the same tag, so the tags looked published.
Dockerfile.operator:27 builds with -mod=vendor, and vendor/ had drifted from
go.mod in both directions:
- go.opentelemetry.io/otel/{metric,trace}: in vendor/modules.txt, not in go.mod
- github.com/luxfi/{crypto,geth,ids,keys,zap,address,age,cache,constants,
container,formatting,math,go-bip32,go-bip39}: in go.mod, not marked explicit
`go mod vendor` alone could not fix it — it aborted first on go.sum entries
missing for the k8s packages cmd/kms-operator imports (k8s.io/api/core/v1,
k8s.io/apimachinery/..., k8s.io/client-go/{dynamic,kubernetes,rest}). So:
go mod tidy (adds them, drops now-unused indirects) then go mod vendor.
Verified by stash control:
operator, -mod=vendor: rc=1 -> rc=0 ("inconsistent vendoring" 1 -> 0)
server, -mod=vendor: rc=1 -> rc=1 (unchanged)
The server's vendor build was already broken and stays broken, for an unrelated
reason: blst.h has never been vendored (confirmed absent from HEAD's tree, so it
could not have worked before either) — go mod vendor does not copy cgo headers
that live outside the package dir. It is not a regression and does not affect
CI: the server's Dockerfile builds with GOFLAGS=-mod=mod after `rm -f go.sum &&
go mod download`, i.e. from the module cache, never from vendor/. The operator
is the only -mod=vendor consumer, which is exactly why it was the only failure.
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
173 lines
4.0 KiB
Go
173 lines
4.0 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package formatting
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
|
|
"github.com/luxfi/crypto/hash"
|
|
)
|
|
|
|
const (
|
|
hexPrefix = "0x"
|
|
checksumLen = 4
|
|
)
|
|
|
|
var (
|
|
errEncodingOverFlow = errors.New("encoding overflow")
|
|
errInvalidEncoding = errors.New("invalid encoding")
|
|
errUnsupportedEncodingInMethod = errors.New("unsupported encoding in method")
|
|
errMissingChecksum = errors.New("input string is smaller than the checksum size")
|
|
errBadChecksum = errors.New("invalid input checksum")
|
|
errMissingHexPrefix = errors.New("missing 0x prefix to hex encoding")
|
|
)
|
|
|
|
// Encoding defines how bytes are converted to a string and vice versa
|
|
type Encoding uint8
|
|
|
|
const (
|
|
// Hex specifies a hex plus 4 byte checksum encoding format
|
|
Hex Encoding = iota
|
|
// HexNC specifies a hex encoding format
|
|
HexNC
|
|
// HexC specifies a hex plus 4 byte checksum encoding format
|
|
HexC
|
|
// JSON specifies the JSON encoding format
|
|
JSON
|
|
)
|
|
|
|
func (enc Encoding) String() string {
|
|
switch enc {
|
|
case Hex:
|
|
return "hex"
|
|
case HexNC:
|
|
return "hexnc"
|
|
case HexC:
|
|
return "hexc"
|
|
case JSON:
|
|
return "json"
|
|
default:
|
|
return errInvalidEncoding.Error()
|
|
}
|
|
}
|
|
|
|
func (enc Encoding) valid() bool {
|
|
switch enc {
|
|
case Hex, HexNC, HexC, JSON:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (enc Encoding) MarshalJSON() ([]byte, error) {
|
|
if !enc.valid() {
|
|
return nil, errInvalidEncoding
|
|
}
|
|
return []byte(`"` + enc.String() + `"`), nil
|
|
}
|
|
|
|
func (enc *Encoding) UnmarshalJSON(b []byte) error {
|
|
str := string(b)
|
|
if str == "null" {
|
|
return nil
|
|
}
|
|
switch strings.ToLower(str) {
|
|
case `"hex"`:
|
|
*enc = Hex
|
|
case `"hexnc"`:
|
|
*enc = HexNC
|
|
case `"hexc"`:
|
|
*enc = HexC
|
|
case `"json"`:
|
|
*enc = JSON
|
|
default:
|
|
return errInvalidEncoding
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Encode [bytes] to a string using the given encoding format [bytes] may be
|
|
// nil, in which case it will be treated the same as an empty slice.
|
|
func Encode(encoding Encoding, bytes []byte) (string, error) {
|
|
if !encoding.valid() {
|
|
return "", errInvalidEncoding
|
|
}
|
|
|
|
switch encoding {
|
|
case Hex, HexC:
|
|
bytesLen := len(bytes)
|
|
if bytesLen > math.MaxInt32-checksumLen {
|
|
return "", errEncodingOverFlow
|
|
}
|
|
checked := make([]byte, bytesLen+checksumLen)
|
|
copy(checked, bytes)
|
|
copy(checked[len(bytes):], hash.Checksum(bytes, checksumLen))
|
|
bytes = checked
|
|
}
|
|
|
|
switch encoding {
|
|
case Hex, HexNC, HexC:
|
|
return fmt.Sprintf("0x%x", bytes), nil
|
|
case JSON:
|
|
// JSON Marshal does not support []byte input and we rely on the
|
|
// router's json marshalling to marshal our interface{} into JSON
|
|
// in response. Therefore it is not supported in this call.
|
|
return "", errUnsupportedEncodingInMethod
|
|
default:
|
|
return "", errInvalidEncoding
|
|
}
|
|
}
|
|
|
|
// Decode [str] to bytes using the given encoding
|
|
// If [str] is the empty string, returns a nil byte slice and nil error
|
|
func Decode(encoding Encoding, str string) ([]byte, error) {
|
|
switch {
|
|
case !encoding.valid():
|
|
return nil, errInvalidEncoding
|
|
case len(str) == 0:
|
|
return nil, nil
|
|
}
|
|
|
|
var (
|
|
decodedBytes []byte
|
|
err error
|
|
)
|
|
switch encoding {
|
|
case Hex, HexNC, HexC:
|
|
if !strings.HasPrefix(str, hexPrefix) {
|
|
return nil, errMissingHexPrefix
|
|
}
|
|
decodedBytes, err = hex.DecodeString(str[2:])
|
|
case JSON:
|
|
// JSON unmarshalling requires interface and has no return values
|
|
// contrary to this method, therefore it is not supported in this call
|
|
return nil, errUnsupportedEncodingInMethod
|
|
default:
|
|
return nil, errInvalidEncoding
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch encoding {
|
|
case Hex, HexC:
|
|
if len(decodedBytes) < checksumLen {
|
|
return nil, errMissingChecksum
|
|
}
|
|
// Verify the checksum
|
|
rawBytes := decodedBytes[:len(decodedBytes)-checksumLen]
|
|
checksum := decodedBytes[len(decodedBytes)-checksumLen:]
|
|
if !bytes.Equal(checksum, hash.Checksum(rawBytes, checksumLen)) {
|
|
return nil, errBadChecksum
|
|
}
|
|
decodedBytes = rawBytes
|
|
}
|
|
return decodedBytes, nil
|
|
}
|