{"record":{"id":"b553116d52430bfb","repo":"canopy-network/canopy","slug":"invalid-public-key","errorCode":null,"errorMessage":"invalid public key","messagePattern":"invalid public key","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/crypto/bls.go","lineNumber":307,"sourceCode":"\n// NewAccountAuthMultiBLSFromPoints creates a multisig public key intended for account authorization.\n// Unlike the consensus-oriented constructor, this requires a positive threshold so callers cannot\n// accidentally create an open multisig account.\nfunc NewAccountAuthMultiBLSFromPoints(publicKeys []kyber.Point, bitmap []byte, threshold uint32) (MultiPublicKeyI, error) {\n\tif threshold == 0 {\n\t\treturn nil, errAccountAuthThreshold\n\t}\n\tmask, err := sign.NewMask(newBLSSuite(), publicKeys, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif bitmap != nil {\n\t\tif err = mask.SetMask(bitmap); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif threshold > uint32(len(mask.Publics())) {\n\t\treturn nil, errors.New(\"invalid public key\")\n\t}\n\treturn newBLSMultiPublicKey(mask, threshold), nil\n}\n\n// NewMultiBLSFromPublicKey creates a BLS multikey from serialized bytes.\n// The encoded public key order is preserved exactly so bitmap signer indices survive a Bytes()/decode roundtrip.\nfunc NewMultiBLSFromPublicKey(publicKey []byte) (MultiPublicKeyI, error) {\n\tsize, errInvalidPK := len(publicKey), errors.New(\"invalid public key\")\n\tif size == 0 || size > 1_000_000 {\n\t\treturn nil, errInvalidPK\n\t}\n\t// unmarshal into a multi-public-key\n\tmpk := new(MultiPublicKey)\n\tif err := proto.Unmarshal(publicKey, mpk); err != nil {\n\t\treturn nil, err\n\t}\n\t// sanity check the size\n\tif len(mpk.PublicKeys) == 0 || len(mpk.Bitmap) == 0 || mpk.Threshold > uint32(len(mpk.PublicKeys)) {","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/canopy-network/canopy/blob/ee8197d91dd410f6592cb650a94c925ee6dc8bad/lib/crypto/bls.go#L289-L325","documentation":"NewAccountAuthMultiBLSFromPoints returns \"invalid public key\" when the requested threshold exceeds the number of public keys in the constructed mask. Requiring more signers than exist would make the multisig impossible to satisfy, so the constructor rejects it.","triggerScenarios":"NewAccountAuthMultiBLSFromPoints called with threshold > len(publicKeys), e.g. threshold 3 with only 2 keys supplied.","commonSituations":"Mismatch between a configured threshold value and the actual signer set passed in; trimming the key list during refactoring; loading a config where threshold and signer list come from different sources.","solutions":["Ensure threshold <= len(publicKeys) before calling","Pass the full signer list, or lower the threshold to match the supplied keys","Log/validate the signer set and threshold pair at config load time"],"exampleFix":"// before\nmpk, _ := crypto.NewAccountAuthMultiBLSFromPoints(points, bitmap, 3) // len(points)==2\n// after\nthreshold := uint32(3)\nif threshold > uint32(len(points)) { threshold = uint32(len(points)) }\nmpk, _ := crypto.NewAccountAuthMultiBLSFromPoints(points, bitmap, threshold)","handlingStrategy":"validation","validationCode":"if threshold > uint32(len(publicKeys)) {\n\treturn errors.New(\"threshold exceeds signer count\")\n}\nmpk, err := crypto.NewAccountAuthMultiBLSFromPoints(publicKeys, bitmap, threshold)","typeGuard":null,"tryCatchPattern":"mpk, err := crypto.NewAccountAuthMultiBLSFromPoints(points, bitmap, threshold)\nif err != nil {\n\treturn nil, fmt.Errorf(\"threshold %d vs %d signers: %w\", threshold, len(points), err)\n}","preventionTips":["Keep threshold and signer list in the same config source","Clamp threshold to len(signers) at load time","Test the signer list length after every refactor"],"tags":["bls","multisig","validation"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"ee8197d91dd410f6592cb650a94c925ee6dc8bad","analyzedAt":"2026-09-06T09:30:15.973Z","contentChangedAt":"2026-09-06T09:30:15.973Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}