Documentation
¶
Overview ¶
Package proof parses, downloads, and converts Truestamp proof bundles in both JSON and CBOR wire formats. Proofs are the self-contained artifacts consumers receive from the API; this package handles only serialization and I/O. Cryptographic verification lives in internal/verify.
The model deliberately keeps every hashed map (the subject's claims or entropy payload, both metadata maps, every block metadata map, and every entropy witness payload) as the raw JSON the wire carried, so that RFC 8785 canonicalization sees the producer's bytes: integers stay exact, no value is coerced, and nothing is re-cased.
Index ¶
- Constants
- Variables
- func CBORToJSON(data []byte) ([]byte, error)
- func Download(rawURL string) ([]byte, error)
- func DownloadCtx(ctx context.Context, rawURL string) ([]byte, error)
- func FileSize(filename string) int64
- func FileSizeFromData(data []byte) int64
- func Generate(apiURL, team, id, subjectType, format string, witnesses WitnessSelection) ([]byte, error)
- func GenerateCtx(ctx context.Context, apiURL, team, id, subjectType, format string, ...) ([]byte, error)
- func HasCBORTag(data []byte) bool
- func IsCBORProof(data []byte) bool
- func IsCommittedWitnessName(name string) bool
- func IsEntropyWitnessName(name string) bool
- func IsWitnessName(name string) bool
- func JSONToCBOR(doc []byte) ([]byte, error)
- func Rejectf(code, format string, args ...any) error
- func RejectionAdvice(code string) string
- func RejectionCode(err error) string
- func WitnessBasis(name string) string
- type BlockMap
- type Bundle
- type Commitment
- type GenerateAPIError
- type IDType
- type Integer
- type KeyEvent
- type Object
- func (o Object) Has(key string) bool
- func (o Object) HasKey(key string) bool
- func (o Object) Integer(key string) (Integer, bool)
- func (o Object) IsString(key string) bool
- func (o Object) Keys() []string
- func (o Object) List(key string) ([]json.RawMessage, bool)
- func (o Object) Literal(key string) string
- func (o Object) Object(key string) (Object, bool)
- func (o Object) Raw(key string) json.RawMessage
- func (o Object) Str(key string) string
- func (o Object) String(key string) (string, bool)
- type RejectionError
- type SigningKeyEvent
- type Subject
- type WitnessSelection
Constants ¶
const ( CodeNotAJSONObject = "not_a_json_object" CodeInvalidSubjectData = "invalid_subject_data" CodeUnsupportedLayout = "unsupported_layout" CodeInvalidSubjectType = "invalid_subject_type" CodeMissingBlock = "missing_block" CodeMissingMetadata = "missing_metadata" CodeNoExternalCommitments = "no_external_commitments" CodeInvalidCommitmentEntry = "invalid_commitment_entry" CodeUnexpectedSubjectFieldsForBlockLike = "unexpected_subject_fields_for_block_like" CodeMissingSubject = "missing_subject" CodeMissingInclusionProof = "missing_inclusion_proof" // CodeSubjectTypeMismatch is the one rejection Appendix E does not // define: it is raised when the caller asserted a subject type // (`verify --type`) and the bundle's own signed `type` differs. The // server names the same condition the same way on /proof/verify. It // is a rejection rather than a graded row because E.25 forbids a // verifier adding a `fail` row for a step Appendix D.4 does not // report. CodeSubjectTypeMismatch = "subject_type_mismatch" )
Hard-rejection identifiers from the whitepaper's error taxonomy (Appendix E.23). A hard rejection aborts before any report exists (E.6), and independent verifiers are required to agree on this vocabulary so their outcomes are comparable, which is only possible if the identifier travels with the error rather than living in prose.
const ( WitnessBlock = "block" WitnessEntropyStellar = "entropy_stellar" WitnessEntropyNIST = "entropy_nist" WitnessEntropyBitcoin = "entropy_bitcoin" WitnessSigningKeyEvent = "signing_key_event" )
The witness registry (Appendix E.17a). A witness is a public record that existed before the submission and that the subject's composite fingerprint commits to; witnesses open the submitted-after edge of the submission window. A commitment, by contrast, is a public-chain transaction recorded after the submission; commitments close the submitted-before edge and are never witnesses.
Names are never renamed and never removed. A new witness type claims a new name, and a verifier that meets a name it does not know reports a visible `skip`, never a failure (E.24).
Variables ¶
var CommittedWitnessNames = []string{ WitnessBlock, WitnessEntropyStellar, WitnessEntropyNIST, WitnessEntropyBitcoin, }
CommittedWitnessNames are the witnesses an item's metadata commits to. `signing_key_event` is a witness of the signature, carried at the top level, and is never committed in the subject metadata.
var EntropyWitnessNames = []string{ WitnessEntropyStellar, WitnessEntropyNIST, WitnessEntropyBitcoin, }
EntropyWitnessNames are the three entropy witnesses, each hashed under 0x21 over the JCS of its carried payload.
var WitnessNames = []string{ WitnessBlock, WitnessEntropyStellar, WitnessEntropyNIST, WitnessEntropyBitcoin, WitnessSigningKeyEvent, }
WitnessNames is every registered witness name, in registry order. It is the vocabulary the `witnesses` argument of proof generation accepts.
Functions ¶
func CBORToJSON ¶ added in v0.13.0
CBORToJSON converts a CBOR proof bundle to the equivalent JSON document by applying Appendix E.3's field-type correspondence:
- `public_key` and `signature` byte strings become padded base64 text;
- every byte string in a hash slot (each block map's previous_block_hash, merkle_root and signing_key_id; subject.signing_key_id; each commitment's epoch_merkle_root, transaction_hash and block_merkle_root) becomes lowercase hex text;
- every map that is a JCS preimage (subject.claims, subject.entropy, subject.metadata, every block metadata map, every entropy witness payload) is converted strictly within the JSON value space, and any value with no JSON counterpart inside one (a byte string, a tag, `undefined`, a simple value other than true/false/null, a non-finite float, a non-text key, text that is not UTF-8) is the hard rejection `invalid_subject_data`;
- `inclusion_proof`, `epoch_proof`, `txoutproof` and `raw_transaction` are text on the wire; a byte string in one of those slots renders as null, so a required one is refused by the E.6 gate the reference verifier applies and an optional one reads as absent;
- everything else keeps its JSON type. A byte string in an unnamed position renders as hex text and a tag is unwrapped, so an unknown optional field is carried through rather than refused (E.24).
The invariant this preserves is E.3's: every hash derived from the CBOR bundle equals the hash derived from the equivalent JSON bundle. Integers are rendered exactly, floats per their IEEE-754 value, and map members in wire order.
func Download ¶
Download fetches a proof bundle from a URL using context.Background. Prefer DownloadCtx when a cancellable context is available.
func DownloadCtx ¶ added in v0.3.0
DownloadCtx is the context-aware variant of Download. Honours ctx for cancellation (e.g. Ctrl-C while a proof is streaming).
func FileSizeFromData ¶
FileSizeFromData returns the byte length of proof data.
func Generate ¶
func Generate(apiURL, team, id, subjectType, format string, witnesses WitnessSelection) ([]byte, error)
Generate calls GenerateCtx with context.Background.
func GenerateCtx ¶ added in v0.3.0
func GenerateCtx(ctx context.Context, apiURL, team, id, subjectType, format string, witnesses WitnessSelection) ([]byte, error)
GenerateCtx requests a proof bundle from the Truestamp API for the given subject ID. subjectType MUST be one of the six registry names (the server does no auto-detection):
item | entropy_nist | entropy_stellar | entropy_bitcoin | block | beacon
format is "json" or "cbor". witnesses selects which witness details the bundle carries. Returns raw bytes ready to write to a file (pretty JSON, with every number literal preserved, or decoded CBOR binary). ctx cancels the in-flight request. The credential is applied by the process-wide auth.Authorizer.
func HasCBORTag ¶ added in v0.12.0
HasCBORTag reports whether data begins with the RFC 8949 self-describing tag 55799 (0xd9 0xd9 0xf7).
func IsCBORProof ¶
IsCBORProof reports whether data is a CBOR proof bundle. Appendix E.3 requires a verifier to accept CBOR both wrapped in the self-describing tag 55799 and as a bare map, so a bare CBOR map (major type 5, first byte 0xa0-0xbf, definite or indefinite length) counts too. Those bytes are UTF-8 continuation bytes and can never open a valid JSON document, so widening the check cannot steal input from the JSON path.
func IsCommittedWitnessName ¶ added in v0.13.0
IsCommittedWitnessName reports whether name is a witness the subject metadata can commit to (every registered name but signing_key_event).
func IsEntropyWitnessName ¶ added in v0.13.0
IsEntropyWitnessName reports whether name is one of the three entropy witnesses.
func IsWitnessName ¶ added in v0.13.0
IsWitnessName reports whether name is a registered witness name.
func JSONToCBOR ¶ added in v0.13.0
JSONToCBOR converts a JSON proof bundle to its CBOR wire form, the exact inverse of CBORToJSON: `public_key` and `signature` become byte strings from base64, every hash slot becomes a byte string from lowercase hex (uppercase is refused rather than laundered into a byte string the verifier would then accept), every other value keeps its JSON type, and integers are preserved exactly. The output is core-deterministic and wrapped in the self-describing tag 55799.
func RejectionAdvice ¶ added in v0.13.0
RejectionAdvice returns the operator instruction for a rejection code, matching the reference verifier's wording.
func RejectionCode ¶ added in v0.12.0
RejectionCode returns the E.23 identifier carried by err, or "" when err is not a hard rejection. Callers use it to distinguish "this bundle was refused at the structural layer" from "verification produced a report".
func WitnessBasis ¶ added in v0.13.0
WitnessBasis names the time a witness publishes, in the words Appendix E.20's report rows are required to use. "" for a witness that publishes no time of its own.
Types ¶
type BlockMap ¶ added in v0.13.0
type BlockMap struct {
// Fields is the map as carried; nil when the value was not a map.
Fields Object
ID string // "" unless carried as a JSON string
PreviousBlockHash string
MerkleRoot string
SigningKeyID string
// Metadata is the block metadata map exactly as carried; nil unless a
// JSON object.
Metadata json.RawMessage
}
BlockMap is the five-field block shape that appears as the top-level `block`, each `block_path` entry, the `block` witness detail, and `signing_key_event.block`. Every one of them derives its hash by the single procedure of Appendix E.14.
type Bundle ¶ added in v0.13.0
type Bundle struct {
// JSON is the document this bundle was parsed from: the input bytes for
// JSON input, or the JSON-value-space conversion of the input for CBOR
// input. It is what MarshalJSON returns and what MarshalCBOR encodes.
JSON []byte
// FromCBOR records which serialization the input arrived in.
FromCBOR bool
// Version is `version` when it is an exact JSON integer, else 0. The
// literal as carried is kept for the E.8 message.
Version int
VersionLiteral json.RawMessage
// Type is the registry name and Code its frozen integer code (E.24).
// Both are validated at parse: an unknown name is a hard rejection.
Type string
Code ptype.Code
GeneratedAt string // "" unless carried as a JSON string
PublicKey string // padded base64, "" unless carried as a JSON string
Signature string // padded base64, "" unless carried as a JSON string
// Subject is nil for block-like subjects and non-nil otherwise.
Subject *Subject
// InclusionProof is "" for block-like subjects and the carried string
// otherwise (an empty string parses and fails the E.12 decode).
InclusionProof string
Block BlockMap
// BlockPath is the ordered list of block maps linking the head block to
// the containing block. nil when absent, not a list, or empty.
BlockPath []BlockMap
// Commitments has at least one entry, each of which passed the E.6
// per-entry gate (a map, a registered chain, a string epoch_proof, a
// present epoch_merkle_root).
Commitments []Commitment
// SigningKeyEvent is nil when the key is absent or null.
SigningKeyEvent *SigningKeyEvent
// Fields is the top-level object as carried.
Fields Object
}
Bundle is a parsed version 1 proof bundle. Normative reference: Appendix E of `truestamp-v2/whitepaper/whitepaper.typ`; the wire shape is described in `kb/proof-bundle-format.md`.
Only the Appendix E.6 hard rejections abort a parse. Every other defect (a wrong `version`, an undecodable `public_key`, a mis-cased hash) parses cleanly so the verification pipeline can grade it as a step result.
func ParseBytes ¶
ParseBytes parses a proof from raw bytes, dispatching to ParseCBOR for CBOR input and to ParseJSON otherwise.
Only the hard rejections Appendix E.6 enumerates abort here, in E.6's order, so that two verifiers handed one malformed bundle name the same first defect. Every abort returns a RejectionError carrying its E.23 identifier. Everything else parses cleanly for the pipeline to grade.
func ParseCBOR ¶
ParseCBOR parses a CBOR proof bundle, tagged (55799) or bare. The input is first converted to the JSON value space per Appendix E.3, which is where the `invalid_subject_data` rejection is raised, and the result is then gated and parsed exactly as a JSON bundle would be, so the two serializations grade one logical bundle identically.
func (*Bundle) IsBlockLike ¶ added in v0.13.0
IsBlockLike reports whether the subject is a block or a beacon.
func (*Bundle) IsEntropy ¶ added in v0.13.0
IsEntropy reports whether the subject is an entropy observation.
func (*Bundle) MarshalCBOR ¶ added in v0.13.0
MarshalCBOR produces the CBOR wire form of the bundle by converting its JSON document with JSONToCBOR.
func (*Bundle) MarshalJSON ¶ added in v0.13.0
MarshalJSON returns the bundle's JSON document. For a bundle parsed from JSON this is the input verbatim; for CBOR input it is the JSON-value-space conversion of the input, with byte-string fields rendered per Appendix E.3 and hashed maps kept exactly as decoded.
type Commitment ¶ added in v0.13.0
type Commitment struct {
Fields Object
Chain string
EpochMerkleRoot string // "" when present but not a JSON string
EpochProof string
TransactionHash string
Network string
Timestamp string
// Ledger and BlockHeight are exact integers when HasLedger /
// HasBlockHeight is true. A present value that is not a JSON integer
// leaves the flag false; the consuming confirmation step grades it.
Ledger int
HasLedger bool
BlockHeight int
HasBlockHeight bool
Txoutproof string
RawTransaction string
BlockMerkleRoot string
}
Commitment is one entry of `commitments` (or of `signing_key_event.commitments`). The E.6 gate guarantees Chain is a registered chain name, EpochProof was carried as a string, and epoch_merkle_root was present; everything else is graded downstream.
type GenerateAPIError ¶ added in v0.13.0
GenerateAPIError is a structured error from /proof/generate carrying the server's `meta.code` when one was sent (for example `no_external_commitments` for a subject not yet committed to a public chain, or `invalid_witness` for an unknown witness name).
func (*GenerateAPIError) Error ¶ added in v0.13.0
func (e *GenerateAPIError) Error() string
type IDType ¶
type IDType string
IDType is the syntactic shape of a subject id. It is NOT the subject's semantic kind (item / entropy / block / beacon): /proof/generate requires an explicit `type` from the caller, there is no server-side auto detection (see cmd/download.go's id-shape smart default). The authoritative label for a bundle in hand is its own signed `t`, readable only after ParseBytes / ParseCBOR. Use DetectIDType for pre-flight validation and for sanity-checking positional args.
func DetectIDType ¶
DetectIDType returns the syntactic shape of id. Returns an error for values that are neither a valid ULID nor a parseable UUID.
type Integer ¶ added in v0.13.0
Integer is an exactly parsed JSON integer. Text is its decimal rendering, which messages use so they can never name a truncated stand-in for the value the bundle carries; N holds the value where it fits an int64.
type KeyEvent ¶ added in v0.13.0
type KeyEvent struct {
Type string
KeyID string
PublicKey string
// Sequence is the raw literal, rendered verbatim in the report.
Sequence json.RawMessage
}
KeyEvent is the `key_event` object inside a key-event block's metadata.
type Object ¶ added in v0.13.0
type Object map[string]json.RawMessage
Object is a JSON object as carried on the wire: each member's raw literal, so presence, null-ness and value type stay distinguishable. Appendix E.6's rules are written in terms of all three, and Go's zero values collapse them.
func (Object) Has ¶ added in v0.13.0
Has reports whether the key is present with a non-null value, which is E.6's presence rule for every other gate.
func (Object) HasKey ¶ added in v0.13.0
HasKey reports whether the key is present at all, null included. The `unsupported_layout` gate is keyed on presence, not on value.
func (Object) Integer ¶ added in v0.13.0
Integer returns the member as an exact integer; ok is false unless the member is a JSON integer literal.
func (Object) IsString ¶ added in v0.13.0
IsString reports whether the member is carried as a JSON string.
func (Object) List ¶ added in v0.13.0
func (o Object) List(key string) ([]json.RawMessage, bool)
List returns the member's elements; ok is false unless it is a JSON array.
func (Object) Literal ¶ added in v0.13.0
Literal renders the member for a report message: the compact JSON literal as carried, or "absent" when the key is missing.
func (Object) Object ¶ added in v0.13.0
Object returns the member as an object; ok is false unless it is one.
func (Object) Raw ¶ added in v0.13.0
func (o Object) Raw(key string) json.RawMessage
Raw returns the member's raw literal, or nil when absent.
func (Object) Str ¶ added in v0.13.0
Str returns the member as a string, or "" when it is absent, null, or of another type.
type RejectionError ¶ added in v0.12.0
RejectionError is a structural hard rejection: the bundle is malformed in a way E.6 says MUST abort before any step runs, so no Report is produced. Code is the E.23 identifier; Detail is the human-facing explanation.
func (*RejectionError) Advice ¶ added in v0.13.0
func (e *RejectionError) Advice() string
Advice returns the one-line operator instruction the reference verifier prints under a rejection.
func (*RejectionError) Error ¶ added in v0.12.0
func (e *RejectionError) Error() string
type SigningKeyEvent ¶ added in v0.13.0
type SigningKeyEvent struct {
// IsMap is false when `signing_key_event` was present but not a map;
// the reference verifier fails that shape rather than skipping it.
IsMap bool
Fields Object
Block BlockMap // Block.IsMap() is false when `block` is absent or not a map
// Commitments holds the entries that pass the E.6 per-entry gate;
// CommitmentCount is how many entries the list carried in total, so a
// list with entries but none valid is distinguishable from no list.
Commitments []Commitment
CommitmentCount int
}
SigningKeyEvent is the optional top-level witness of the signature: the ledger block whose metadata.key_event introduced the signing key, plus that block's own public-chain commitments.
func (*SigningKeyEvent) KeyEvent ¶ added in v0.13.0
func (e *SigningKeyEvent) KeyEvent() (KeyEvent, bool)
KeyEvent reads `block.metadata.key_event` from the carried block map. ok is false when the block carries no key_event map.
type Subject ¶
type Subject struct {
Fields Object
ID string // "" unless carried as a JSON string
// Claims is `subject.claims` exactly as carried (nil when absent or
// null); Entropy likewise for `subject.entropy`. Which one a bundle
// uses follows its type.
Claims json.RawMessage
Entropy json.RawMessage
// Metadata is `subject.metadata` exactly as carried; the E.6 gate
// guarantees it is a JSON object.
Metadata json.RawMessage
SigningKeyID string // "" unless carried as a JSON string
// Witnesses is `subject.witnesses` as carried: witness name to the raw
// detail. nil when absent or not a map. Unknown names are preserved so
// the verifier can report them.
Witnesses Object
}
Subject is the `subject` map of a non-block-like bundle.
func (*Subject) CommittedWitnesses ¶ added in v0.13.0
CommittedWitnesses returns `subject.metadata.witnesses` as carried: witness name to the raw committed value. Empty when the metadata carries no witnesses map.
func (*Subject) Data ¶
func (s *Subject) Data(code ptype.Code) json.RawMessage
Data returns the hashed data map for the subject type: claims for an item, the entropy payload for an entropy subject.
func (*Subject) WitnessNamesCarried ¶ added in v0.13.0
WitnessNamesCarried returns the sorted names under `subject.witnesses`.
type WitnessSelection ¶ added in v0.13.0
type WitnessSelection struct {
// contains filtered or unexported fields
}
WitnessSelection is the `witnesses` argument of proof generation: which witness details the bundle should carry. The zero value selects every witness (the complete bundle); NoWitnesses selects none (the compact bundle); SelectWitnesses selects a subset (a partial bundle). All three are ordinary version 1 bundles.
func AllWitnesses ¶ added in v0.13.0
func AllWitnesses() WitnessSelection
AllWitnesses selects every witness; the argument is omitted from the request.
func NoWitnesses ¶ added in v0.13.0
func NoWitnesses() WitnessSelection
NoWitnesses selects no witness details; the request carries `[]`.
func ParseWitnessSelection ¶ added in v0.13.0
func ParseWitnessSelection(flag string) (WitnessSelection, error)
ParseWitnessSelection parses a `--witnesses` flag value: "" or "all" selects every witness, "none" selects none, and a comma-separated list selects a subset.
func SelectWitnesses ¶ added in v0.13.0
func SelectWitnesses(names []string) (WitnessSelection, error)
SelectWitnesses selects the named witnesses. Every name must be a registered witness name (the server rejects an unknown one with `invalid_witness`, and so does this).
func (WitnessSelection) FilenameSuffix ¶ added in v0.13.0
func (w WitnessSelection) FilenameSuffix() string
FilenameSuffix returns the artifact filename suffix Appendix E.2 gives each variant: "" for complete, "-compact" for none, "-partial" for a subset.
func (WitnessSelection) IsAll ¶ added in v0.13.0
func (w WitnessSelection) IsAll() bool
IsAll reports whether every witness is selected.
func (WitnessSelection) IsNone ¶ added in v0.13.0
func (w WitnessSelection) IsNone() bool
IsNone reports whether no witness detail is selected.
func (WitnessSelection) Names ¶ added in v0.13.0
func (w WitnessSelection) Names() []string
Names returns the selected names; nil for every witness.
func (WitnessSelection) String ¶ added in v0.13.0
func (w WitnessSelection) String() string
String renders the selection the way the flag spells it.