// Package datekeys is the reference Go implementation of the DateKeys Protocol // Specification v0.9 (spec/DateKeys_Protocol_Specification_v0.9.md). // // The protocol objects live in subpackages: // // - datekey: DateKey resolution and the canonical dk1_ form (spec §14-§19). // - profile: Provider Profiles and the pinned Quicknet profile (spec §10-§13). // - provider, provider/drand: release sources and local BLS verification (spec §45-§52). // - capsule: the DateKeyCap .dkc container (spec §20-§39, §61-§63). // - accesskey: the DateKeys Access Key .dkk credential (spec §40-§44). // - extension: the generic extension mechanism (spec §54). // // This package holds the normative error catalogue of spec §69. Every protocol // failure returned by this module wraps exactly one of these sentinels, so // callers can match them with [errors.Is] and extract the code with [Code]. package datekeys import "errors" // Error is a normative DateKeys error (spec §69). Values are compared by // identity; use [errors.Is] against the exported sentinels. type Error struct { code string } // Error returns the normative code, for example "ERR_INVALID_MAGIC". func (e *Error) Error() string { return e.code } // Code returns the normative code, for example "ERR_INVALID_MAGIC". func (e *Error) Code() string { return e.code } // Normative errors, spec §69. var ( // ErrInvalidMagic: the object does not start with DKC1 or DKK1 (spec §22, §40). ErrInvalidMagic = &Error{"ERR_INVALID_MAGIC"} // ErrUnsupportedVersion: an unknown framing or schema version (spec §22, §70). ErrUnsupportedVersion = &Error{"ERR_UNSUPPORTED_VERSION"} // ErrInvalidFlags: FLAGS or RESERVED are not zero (spec §22, §40). ErrInvalidFlags = &Error{"ERR_INVALID_FLAGS"} // ErrNonCanonicalCBOR: the bytes are not the unique deterministic CBOR // encoding of a valid instance of the normative schema (spec §58, §58.1). ErrNonCanonicalCBOR = &Error{"ERR_NON_CANONICAL_CBOR"} // ErrUnknownProfile: the DateKey names a profile that is not pinned locally (spec §13). ErrUnknownProfile = &Error{"ERR_UNKNOWN_PROFILE"} // ErrProfileMismatch: a chain hash or profile does not match the pinned profile (spec §35, §63). ErrProfileMismatch = &Error{"ERR_PROFILE_MISMATCH"} // ErrDateKeyInvalid: a DateKey that cannot be decoded or validated (spec §18, §19). ErrDateKeyInvalid = &Error{"ERR_DATEKEY_INVALID"} // ErrDateKeyNonCanonical: a valid DateKey in a non-canonical encoding (spec §19). ErrDateKeyNonCanonical = &Error{"ERR_DATEKEY_NON_CANONICAL"} // ErrRoundMismatch: a round that differs from the locally resolved one (spec §17, §63). ErrRoundMismatch = &Error{"ERR_ROUND_MISMATCH"} // ErrReleaseUnavailable: the release is not published yet or no source delivered it (spec §45-§50). ErrReleaseUnavailable = &Error{"ERR_RELEASE_UNAVAILABLE"} // ErrReleaseInvalid: a release that fails local verification (spec §51). ErrReleaseInvalid = &Error{"ERR_RELEASE_INVALID"} // ErrAccessRequired: the policy requires an access credential and none was supplied (spec §33). ErrAccessRequired = &Error{"ERR_ACCESS_REQUIRED"} // ErrAccessInvalid: the supplied credentials do not open this capsule (spec §33, §38). ErrAccessInvalid = &Error{"ERR_ACCESS_INVALID"} // ErrPolicyStructureMismatch: the cryptographic structure does not match the // declared access policy or the stanza rules of V1 (spec §25, §29, §32, §33, §36). ErrPolicyStructureMismatch = &Error{"ERR_POLICY_STRUCTURE_MISMATCH"} // ErrHeaderBinding: header_binding does not match PRELUDE || PUBLIC_HEADER (spec §26). ErrHeaderBinding = &Error{"ERR_HEADER_BINDING"} // ErrIntegrity: truncation, corruption or failed authentication of framing or age data (spec §4, §55). ErrIntegrity = &Error{"ERR_INTEGRITY"} // ErrExtensionCriticalUnknown: a critical extension this implementation does not know (spec §54). ErrExtensionCriticalUnknown = &Error{"ERR_EXTENSION_CRITICAL_UNKNOWN"} // ErrExtensionDataInvalid: a known extension whose data does not follow its // registered schema. It rejects the object only for a critical extension; a // noncritical one is reported as unusable (spec §54, §72). ErrExtensionDataInvalid = &Error{"ERR_EXTENSION_DATA_INVALID"} // ErrHeadInvalid: the head of a format 3 capsule is well encoded but one // of its fields breaks its rules: a path, the comment, the declared author // or the layout of the files (spec §29.4 to §29.6). New in v0.10. ErrHeadInvalid = &Error{"ERR_HEAD_INVALID"} ) // All returns every normative error in the order of spec §69. func All() []*Error { return []*Error{ ErrInvalidMagic, ErrUnsupportedVersion, ErrInvalidFlags, ErrNonCanonicalCBOR, ErrUnknownProfile, ErrProfileMismatch, ErrDateKeyInvalid, ErrDateKeyNonCanonical, ErrRoundMismatch, ErrReleaseUnavailable, ErrReleaseInvalid, ErrAccessRequired, ErrAccessInvalid, ErrPolicyStructureMismatch, ErrHeaderBinding, ErrIntegrity, ErrExtensionCriticalUnknown, ErrExtensionDataInvalid, ErrHeadInvalid, } } // Code returns the normative code of the first DateKeys error in err's tree, // or "" if err does not wrap one. func Code(err error) string { var e *Error if errors.As(err, &e) { return e.code } return "" }