canopy-network/canopy · error
account-auth multisig requires threshold > 0
Error message
account-auth multisig requires threshold > 0
What it means
errAccountAuthThreshold is thrown when a BLS multisig account-auth key is constructed with a threshold of 0. A multisig with threshold 0 would allow zero signatures to authorize a transaction, which is meaningless and unsafe, so NewAccountAuthMultiBLSFromPoints and NewAccountAuthMultiBLSFromPublicKey reject it up front.
Source
Thrown at lib/crypto/bls.go:267
// String() returns the hex string representation of the public key
func (b *BLS12381PublicKey) String() string {
return hex.EncodeToString(b.Bytes())
}
var _ MultiPublicKeyI = &BLS12381MultiPublicKey{}
// BLS12381MultiPublicKey is an aggregated public key created by combining multiple BLS public keys from different signers.
// This type intentionally exposes two representations:
// - Address(): canonical multisig account identity for the signer set
// - Bytes()/Bitmap()/AddSigner(): order-preserving verification state where signer indices are meaningful
type BLS12381MultiPublicKey struct {
signatures [][]byte
mask *sign.Mask
scheme *bdn.Scheme
threshold uint32
}
var errAccountAuthThreshold = errors.New("account-auth multisig requires threshold > 0")
// NewBLSMultiPublicKey() creates a new BLS12381MultiPublicKey reference from a kyber mask object
func newBLSMultiPublicKey(mask *sign.Mask, threshold uint32) *BLS12381MultiPublicKey {
return &BLS12381MultiPublicKey{mask: mask, scheme: newBLSScheme(), signatures: make([][]byte, len(mask.Publics())), threshold: threshold}
}
// NewMultiBLSFromPoints() creates a multi public key from a list of G1 points on a BLS12381 curve.
// Important: this preserves caller order for backwards compatibility. Bitmap indices and AddSigner() indices refer to
// this exact order, so this constructor must not canonicalize or sort the signer list.
func NewMultiBLSFromPoints(publicKeys []kyber.Point, bitmap []byte) (MultiPublicKeyI, error) {
mask, err := sign.NewMask(newBLSSuite(), publicKeys, nil)
if err != nil {
return nil, err
}
if bitmap != nil {
if err = mask.SetMask(bitmap); err != nil {
return nil, err
}View on GitHub (pinned to ee8197d91d)
Solutions
- Pass a threshold >= 1 (and <= number of public keys) when calling NewAccountAuthMultiBLSFromPoints
- Set the threshold field on the serialized MultiPublicKey before NewMultiBLSFromPublicKey/NewAccountAuthMultiBLSFromPublicKey
- Validate/fix stored key material and re-serialize it with a correct threshold
Example fix
// before
key, _ := crypto.NewAccountAuthMultiBLSFromPoints(points, bitmap, 0)
// after
threshold := uint32(2)
if threshold == 0 || threshold > uint32(len(points)) { threshold = uint32(len(points)) }
key, _ := crypto.NewAccountAuthMultiBLSFromPoints(points, bitmap, threshold) Defensive patterns
Strategy: validation
Validate before calling
if threshold == 0 || threshold > uint32(len(publicKeys)) {
return errors.New("threshold must be in [1, len(publicKeys)]")
}
key, err := crypto.NewAccountAuthMultiBLSFromPoints(publicKeys, bitmap, threshold) Try / catch
key, err := crypto.NewAccountAuthMultiBLSFromPoints(points, bitmap, threshold)
if err != nil {
return fmt.Errorf("multisig construction: %w", err)
} Prevention
- Always derive threshold from config with a default > 0
- When deserializing keys, verify the decoded threshold before using them in account auth
- Add unit tests asserting constructors reject threshold 0
When it happens
Trigger: Calling NewAccountAuthMultiBLSFromPoints(publicKeys, bitmap, 0), or NewAccountAuthMultiBLSFromPublicKey with serialized bytes whose decoded MultiPublicKey has threshold == 0.
Common situations: Threshold field left at its zero value in config/structs, deserializing keys produced by older library versions that did not persist a threshold, or copying constructors without setting the threshold parameter.
Related errors
- invalid public key
- duplicate bls public key
- Item too long: {len(item)} bytes (max 255)
- Invalid uint64 value: {value}
- Invalid chain_id: {self.chain_id}
AI-assisted analysis of canopy-network/canopy@ee8197d91d (2026-09-06).
Data as JSON: /api/errors/5c7122c66cc6e93c.
Report an issue: GitHub.