Skip to main content

001 · BitFS Quote Credential Specification

Encoding, Signing, and Hashing

All structures use RFC 8949 core deterministic CBOR. TermsCBOR MUST be the raw deterministic CBOR bytes of FileQuoteTerms:

TermsSignature = Sign_seller(TermsCBOR)
Verify(SellerPubkey, TermsCBOR, TermsSignature)
FileQuoteTermsHash = SHA256(TermsCBOR)

No signature domain is used. Implementations MUST verify TermsSignature solely against the quote terms as described above.

The normative CDDL is located at https://github.com/bsv8/go-bitfs/blob/main/spec/file-quote.cddl.

FileQuoteTerms

CBOR array positions are fixed as follows:

PositionFieldImplementation Requirement
0versionCurrently 1.
1seed_hashMUST be 32 bytes.
2buyer_pubkeyOnly this public key MAY accept and sign subsequent purchase requests.
3seed_price_satSeed price in satoshis.
4full_block_price_satFull 256 KiB block price in satoshis.
5file_sizeTotal file size in bytes.
6quote_expires_at_unixQuote expiration as a Unix timestamp in seconds.
7supported_arbiter_pubkeys_cborIndependent deterministic CBOR of an array of arbiter public keys.

The block count MUST be derived from file_size: 0 maps to 0 blocks; a positive value maps to ceil(file_size / 262144). The current seed payload limit is 256 KiB; the maximum quote size is 8192 blocks. The arbiter public key array MAY be empty, but public keys within it MUST NOT be empty or duplicated.

SignedFileQuote

CBOR array positions are fixed as follows:

PositionFieldImplementation Requirement
0versionCurrently 1.
1terms_cborFull raw CBOR of FileQuoteTerms.
2seller_pubkeyUsed to verify the terms signature.
3terms_signatureSeller's signature over terms_cbor.
4recommended_filenameDisplay suggestion only; MUST NOT be treated as ground truth for content, price, or identity.

During verification, implementations MUST re-decode and deterministically re-encode terms_cbor, then verify the signature, field lengths, quote expiration, and arbiter array. Clients displaying the filename MUST sanitize path separators and control characters.

Subsequent References and Retention

Normal messages in 003 carry only FileQuoteTermsHash. The seller MUST locate and re-verify the original quote credential by this hash; both parties MUST retain the full quote credential until the associated payment settlement and arbitration window has closed. For offline verification, migration, or arbitration, the full quote credential together with subsequent credentials constitutes the evidence package.

Tail Block

Quotes do not carry a tail-block price. Implementations MUST calculate the tail block proportionally based on its actual length relative to 256 KiB, applying a 10% calculation tolerance concession on the seller's side. This rule is not the sole integer formula for V1 automatic arbitration; the cumulative amount signed out by the buyer in 005 is the final enforceable amount.

Go API

arbiterCBOR, err := bitfs.EncodeSupportedArbiterPubkeys(arbiterPubkeys)
terms := &bitfs.FileQuoteTerms{
SeedHash: seedHash,
BuyerPubkey: buyerPubkey,
SeedPriceSat: 10,
FullBlockPriceSat: 100,
FileSize: fileSize,
QuoteExpiresAtUnix: expiresAtUnix,
SupportedArbiterPubkeysCBOR: arbiterCBOR,
}
quote, err := bitfs.NewSignedFileQuote(terms, sellerPubkey, "download.bin", signTermsCBOR)
verifiedTerms, err := bitfs.VerifySignedFileQuote(quote, verifySellerTermsSignature)

The caller is responsible for specifying public key format, signing algorithm, and signature verifier; the library does not bind to any wallet or elliptic curve implementation.