Documentation
¶
Overview ¶
Package boxrec is the byte-level contract of bbox: the envelope record an envelope carrier holds, the receipt record a receipt carrier holds, the BRC-169 envelope a record's content is, the office and box name grammars, and the lookup question classes. docs/spec.md is the normative text; this package generates the golden vectors under testdata/vectors.
Every record is canonical CBOR through bcommon's cbor package, so one value has one encoding a reader accepts. Every decoder bounds its input before the CBOR decoder runs, and the CBOR decoder bounds every declared length against the bytes present before it allocates.
Index ¶
- Constants
- Variables
- func Canonical(v any) ([]byte, error)
- func CheckBox(s string) error
- func CheckIdentity(k []byte) error
- func CheckOffice(s string) error
- func CheckOfficeName(name string) error
- func CheckPayment(ctx context.Context, w KeyGetter, originator string, e *Envelope, p *Payment, ...) (*transaction.Transaction, error)
- func EncodePlaintext(doc *Object) ([]byte, error)
- func FundingScript(key *ec.PublicKey) []byte
- func IsEnvelope(payload []byte) bool
- func IsFundingShape(s []byte) bool
- func IsReceipt(payload []byte) bool
- func Mined(ctx context.Context, tx *transaction.Transaction, ...) bool
- func MinimalPath(mp *transaction.MerklePath, txid *chainhash.Hash) (*transaction.MerklePath, error)
- func NewOffice(name string, r io.Reader) (string, error)
- func Open(ctx context.Context, w Decrypter, originator string, c *Content, from []byte) ([]byte, error)
- func P2PKH(key *ec.PublicKey) []byte
- func Params() carrier.Params
- func ParseAfter(s string) (uint64, string, bool)
- func ParseJSON(b []byte) (any, error)
- func ParseOutpoint(s string) (string, uint32, bool)
- func PushDropScript(key *ec.PublicKey, fields [][]byte, sig []byte) []byte
- func RFC3339(t uint64) string
- func Reason(err error) string
- func Seal(ctx context.Context, w Signer, originator string, doc *Object, brc78 []byte) ([]byte, error)
- func SealEnvelope(ctx context.Context, w Sealer, originator string, from, to, plaintext []byte, ...) ([]byte, error)
- func SplitOffice(s string) (name, suffix string, err error)
- func StrictSignature(der []byte) bool
- func Topic(office string) (string, error)
- type Admission
- type Carrier
- type Class
- type Content
- type Decrypter
- type Envelope
- type Host
- type Int
- type KeyGetter
- type Kind
- type Member
- type Object
- type Payment
- type PaymentOutput
- type Plaintext
- type Question
- type Receipt
- type Ref
- type Sealer
- type Signer
- type TxKind
Examples ¶
Constants ¶
const ( // ProtocolName is the BRC-43 protocol name, security level 1. BRC-43 // key derivation refuses a name under five characters, so the // application name alone ("bbox") cannot be the protocol name. ProtocolName = "bbox message" // KeyEnvelope locks every carrier's record output (envelopes and // receipts), signs its field, and locks the funding-tree outputs a // carrier spends. KeyEnvelope = "envelope" // KeySignature signs the BRC-169 envelope a record's content is. KeySignature = "signature" // KeyFund is the embedded wallet's funding key. KeyFund = "fund" // TopicPrefix and LookupService are the overlay names (BRC-87). TopicPrefix = "tm_bbox_" LookupService = "ls_bbox" )
Registry values (docs/frozen.md); frozen once the first record is published to a public host.
const ( // MaxSafe is 2^53 - 1. MaxSafe = 1<<53 - 1 // MaxTime is 9999-12-31T23:59:59Z, the last second RFC 3339 can write. MaxTime = 253402300799 // SuffixLen is the length of an office's random suffix. SuffixLen = 10 // MaxOffice is the longest office identifier: BRC-87 caps a name at 50 // characters and the topic prefix takes 8. MaxOffice = 50 - len(TopicPrefix) // MaxOfficeName is the longest readable part of an office identifier. MaxOfficeName = MaxOffice - 1 - SuffixLen // MinOffice is the shortest office identifier. MinOffice = 1 + 1 + SuffixLen // MaxBox is the longest box name. MaxBox = 50 // MaxContent bounds an envelope's content (key 7), the BRC-169 // envelope as carried, in bytes. MaxContent = 16 << 10 // MaxEnvelopeRecord bounds an encoded envelope record. MaxEnvelopeRecord = MaxContent + 4096 // MaxAcks bounds the commitments one receipt acknowledges. MaxAcks = 64 // MaxReceiptRecord bounds an encoded receipt record. MaxReceiptRecord = 4096 // MaxKeys bounds the entries of a record map, unknown keys included. MaxKeys = 64 )
Bounds. A reader accepts every record within them; a later version may raise a bound but never lower it (docs/frozen.md).
const ( EKMagic = 0 EKOffice = 1 EKTo = 2 EKBox = 3 EKFrom = 4 EKCreated = 5 EKExpires = 6 EKContent = 7 )
Envelope record keys.
const ( RKMagic = 0 RKOffice = 1 RKBy = 2 RKAcks = 3 RKCreated = 4 )
Receipt record keys.
const ( MetanetHandles = "1.0" MemberVersion = "metanetHandles" MemberRecipient = "recipient" MemberSender = "sender" MemberCreated = "created" MemberQuoteID = "quoteId" MemberPayment = "payment" MemberContent = "content" MemberSignature = "signature" MemberIdentity = "identityKey" )
BRC-169 envelope members and the one version this contract admits.
const ( PlainBody = "body" PlainPayment = "payment" PlainRefs = "refs" )
Plaintext members (docs/spec.md section 4.5).
const ( // PaymentMinLife is the least expires - created of an envelope whose // payment a recipient takes. PaymentMinLife = 7200 // PaymentMargin is how long before expires a recipient stops // internalizing, and after it a sender may reclaim. PaymentMargin = 3600 )
Payment timing (docs/spec.md section 10), seconds.
const ( QOffice = "office" QTo = "to" QBox = "box" QAfter = "after" QBy = "by" QReceiptFor = "receiptFor" QHistory = "history" QFrom = "from" QSpent = "spent" )
Query member names.
const ( PageEnvelopes = 64 PageReceipts = 8 PageSweeps = 8 )
Page sizes.
const BRC78Min = 4 + 33 + 33 + 32 + 32 + 16
BRC78Min is the shortest BRC-78 message: version, sender, recipient, key id, a 32-byte IV and a 16-byte GCM tag around an empty plaintext.
const DefaultMaxBEEF = 256 << 10
DefaultMaxBEEF is the BEEF bound Admit applies when a host names none: the floor docs/spec.md section 12 sets for a host's own bound.
const MaxRefs = 32
MaxRefs is the most references a plaintext carries (docs/spec.md section 4.5): 32 references with a key and a locator of a hundred bytes take about 8 KB, which fits the plaintext a 16 KiB content can hold with room for a body.
Variables ¶
var ( ErrCarrierShape = errors.New("boxrec: carrier has the wrong shape") ErrBEEF = errors.New("boxrec: BEEF is not exactly the carrier and its proven funding tree") ErrMineable = errors.New("boxrec: carrier is mineable") ErrUnlock = errors.New("boxrec: unlocking script is not in canonical form") ErrLock = errors.New("boxrec: output script is not the canonical one for the owner") ErrSignature = errors.New("boxrec: field signature is not strict or does not verify") ErrFunding = errors.New("boxrec: carrier does not spend a funding output of the owner") ErrUnmined = errors.New("boxrec: sweep has no proof that verifies") ErrNotBbox = errors.New("boxrec: transaction is not for this topic") )
The transaction refusals of docs/spec.md section 8.1, beside the record and content refusals. A transaction is refused for the first rule it breaks. A carrier whose record names another office than the topic's is refused with ErrOffice, the label of a record whose office breaks the grammar.
var ( TagPrefix = []byte("bb") // TagFunding is the one field of a funding-tree output. TagFunding = []byte{'b', 'b', 0x02} // MagicEnvelope is key 0 of an envelope record: "bb", 'e', version 1. MagicEnvelope = []byte{'b', 'b', 'e', 0x01} // MagicReceipt is key 0 of a receipt record: "bb", 'r', version 1. MagicReceipt = []byte{'b', 'b', 'r', 0x01} )
Tags and magics. The tag prefix "bb" belongs to bbox.
var ( Protocol = wallet.Protocol{SecurityLevel: wallet.SecurityLevelEveryApp, Protocol: ProtocolName} EnvelopeDerivation = pushdrop.Derivation{Protocol: Protocol, KeyID: KeyEnvelope} SignatureDerivation = pushdrop.Derivation{Protocol: Protocol, KeyID: KeySignature} FundDerivation = pushdrop.Derivation{Protocol: Protocol, KeyID: KeyFund} )
Derivations under [1, "bbox message"], each with counterparty anyone, so a reader derives the key from the identity key alone.
var ( ErrTooLarge = record.ErrTooLarge ErrCBOR = record.ErrCBOR ErrKeyType = record.ErrKeyType ErrMagic = record.ErrMagic ErrMissing = record.ErrMissing ErrType = record.ErrType ErrRange = record.ErrRange ErrIdentity = errors.New("boxrec: identity key is not a canonical compressed key") ErrOffice = errors.New("boxrec: office identifier breaks the grammar") ErrBox = errors.New("boxrec: box name breaks the grammar") ErrExpires = errors.New("boxrec: expires is not zero and not after created") ErrAcks = errors.New("boxrec: acks are not 1 to 64 distinct commitments in ascending order") ErrContentJSON = errors.New("boxrec: content is not a JSON object in the subset") ErrContentShape = errors.New("boxrec: content is not a bbox BRC-169 envelope") ErrContentCipher = errors.New("boxrec: content's encrypted payload does not match the record") ErrContentSignature = errors.New("boxrec: content signature does not verify") ErrQuery = errors.New("boxrec: question is not one of the defined classes") )
The refusals. A host counts them by Reason.
var ( ErrUndecryptable = errors.New("boxrec: the recipient cannot decrypt the envelope") ErrPlaintextJSON = errors.New("boxrec: plaintext is not a JSON object in the subset") ErrPlaintextShape = errors.New("boxrec: plaintext member has the wrong shape") ErrPaymentShape = errors.New("boxrec: payment has the wrong shape") ErrPaymentExpires = errors.New("boxrec: payment envelope does not expire at least two hours after it was created") ErrPaymentLate = errors.New("boxrec: payment is past its internalization window") ErrPaymentBEEF = errors.New("boxrec: payment is not an Atomic BEEF that parses") ErrPaymentOutput = errors.New("boxrec: payment output does not pay the recipient what it says") ErrPaymentSPV = errors.New("boxrec: payment does not verify against the recipient's headers") )
The recipient's refusals of what it decrypts (docs/spec.md sections 4.5, 10 and 13). A host never sees the plaintext, so none of these is a host rule: they are the recipient client's, in the order a client applies them, and a client that refuses a payment shows the message without it.
var BRC78Version = []byte{0x42, 0x42, 0x10, 0x33}
BRC78Version is the four-byte version a BRC-78 message starts with, as go-sdk v1.5.2's message package writes it.
var Classes = []Class{ {"inbox", []string{QOffice, QTo}, true, PageEnvelopes}, {"inbox-after", []string{QAfter, QOffice, QTo}, true, PageEnvelopes}, {"box", []string{QBox, QOffice, QTo}, true, PageEnvelopes}, {"box-after", []string{QAfter, QBox, QOffice, QTo}, true, PageEnvelopes}, {"sender", []string{QFrom, QOffice, QTo}, true, PageEnvelopes}, {"sender-after", []string{QAfter, QFrom, QOffice, QTo}, true, PageEnvelopes}, {"receipt", []string{QBy, QOffice, QReceiptFor}, true, PageReceipts}, {"sweep", []string{QOffice, QSpent}, true, PageSweeps}, {"history", []string{QHistory, QOffice}, false, PageEnvelopes}, {"history-after", []string{QAfter, QHistory, QOffice}, false, PageEnvelopes}, }
Classes is every question class ls_bbox answers, in the spec's order.
var PaymentProtocol = wallet.Protocol{SecurityLevel: 2, Protocol: "3241645161d8"}
PaymentProtocol is BRC-29's derivation protocol: a payment output is P2PKH to the key derived under it with key id "<prefix> <suffix>".
Functions ¶
func Canonical ¶
Canonical writes v as RFC 8785 serializes it: no white space, object members sorted by the UTF-16 code units of their names, strings escaped as ECMAScript's JSON.stringify escapes them, integers in plain decimal.
func CheckBox ¶
CheckBox applies the box name grammar: 1 to MaxBox bytes of lowercase ASCII letters, digits and single underscores, starting with a letter and ending with a letter or a digit.
func CheckIdentity ¶
CheckIdentity refuses anything but a canonical compressed secp256k1 key (bcommon guard.ParsePubKey): 33 bytes, prefix 0x02 or 0x03, an x-coordinate below the field prime, and a point on the curve. Accepting an alias would let two byte strings name one sender or recipient.
func CheckOffice ¶
CheckOffice applies the office identifier grammar: <name>_<suffix>, where name meets CheckOfficeName and suffix is exactly SuffixLen lowercase ASCII letters. TopicPrefix + office is then a BRC-87 topic manager name.
func CheckOfficeName ¶
CheckOfficeName applies the grammar of an office's readable part: 1 to MaxOfficeName bytes of lowercase ASCII letters and single underscores, starting and ending with a letter.
func CheckPayment ¶
func CheckPayment(ctx context.Context, w KeyGetter, originator string, e *Envelope, p *Payment, headers chaintracker.ChainTracker, now uint64) (*transaction.Transaction, error)
CheckPayment is what a recipient checks before it internalizes a payment from envelope e, at its time now, in order: payment-expires (e expires at least PaymentMinLife after it was created), payment-late (now is before expires - PaymentMargin), payment-beef (an Atomic BEEF that parses, with its subject), payment-output (each listed output exists, holds the satoshis listed, and is P2PKH to the key the recipient's wallet derives under BRC-29 for the prefix, the suffix and the sender), payment-spv (the transaction verifies against the recipient's headers, BRC-67). It returns the payment transaction, for the wallet's internalizeAction.
func EncodePlaintext ¶
EncodePlaintext writes doc as a plaintext: its canonical serialization, held to the recipient's rules (ParsePlaintext) before it is returned, so a sender never seals what the recipient refuses. Members this contract does not define (an application's own, section 4.5) are carried as they are.
Example ¶
An application's own plaintext member rides beside bbox's: written with EncodePlaintext, read back with Extension, its members as the sender wrote them.
package main
import (
"fmt"
"github.com/lightwebinc/bbox/boxrec"
)
func main() {
app := &boxrec.Object{}
app.Set("v", boxrec.Int(1))
app.Set("kind", "dm")
app.Set("seq", boxrec.Int(1))
doc := &boxrec.Object{}
doc.Set(boxrec.PlainBody, "hello")
doc.Set("app", app)
plain, err := boxrec.EncodePlaintext(doc)
if err != nil {
panic(err)
}
fmt.Println(string(plain))
p, err := boxrec.ParsePlaintext(plain)
if err != nil {
panic(err)
}
m, _ := p.Extension("app")
kind, _ := m.Get("kind")
seq, _ := m.Get("seq")
fmt.Println(*p.Body, kind, seq)
// A plaintext the recipient would refuse is not written.
bad := &boxrec.Object{}
bad.Set(boxrec.PlainBody, boxrec.Int(7))
_, err = boxrec.EncodePlaintext(bad)
fmt.Println(boxrec.Reason(err))
}
Output: {"app":{"kind":"dm","seq":1,"v":1},"body":"hello"} hello dm 1 plaintext-shape
func FundingScript ¶
FundingScript is a funding-tree output locked to key: <key> OP_CHECKSIG <62 62 02> OP_DROP.
func IsEnvelope ¶
IsEnvelope reports whether a PushDrop's first field claims to be an envelope record.
func IsFundingShape ¶
IsFundingShape reports whether s is a well-formed funding output under some canonical compressed key: exactly the funding script rebuilt from its own key. Whose key it is cannot be read from the script (the derivation is one way); a carrier's funding rule compares with the owner's, and a sweep takes any.
func Mined ¶
func Mined(ctx context.Context, tx *transaction.Transaction, headers chaintracker.ChainTracker) bool
Mined reports whether tx carries a proof that verifies against the headers. No headers means nothing is mined.
func MinimalPath ¶
func MinimalPath(mp *transaction.MerklePath, txid *chainhash.Hash) (*transaction.MerklePath, error)
MinimalPath is mp cut to the proof of txid alone (spec section 8.1 rule 2): at the lowest level txid, flagged as the txid, and its sibling; above that the one sibling each level needs, computed from the leaves below when mp holds only those. A node may answer a proof that carries more of its block than one transaction needs, and a host refuses a carrier whose funding tree's proof does. The result proves the same root.
func NewOffice ¶
NewOffice creates an office identifier for name: name, an underscore, and SuffixLen letters drawn uniformly at random from a to z by r (crypto/rand.Reader when r is nil). Whoever creates the office calls it once and keeps the result for the office's life.
func Open ¶
func Open(ctx context.Context, w Decrypter, originator string, c *Content, from []byte) ([]byte, error)
Open decrypts an envelope's BRC-78 message through the recipient's wallet: protocol [2, "message encryption"], the message's key id in base64, counterparty the sender. A failure is ErrUndecryptable, which a reader shows as such, never as an empty message.
func Params ¶
Params are the bcommon carrier parameters of a bbox carrier: the record output and funding outputs under [1, "bbox message"] key id envelope, the funding tag, and a payload validator that takes an envelope or a receipt record. A sender mints with carrier.Mint and sweeps with carrier.Sweep under them.
func ParseAfter ¶
ParseAfter parses a page cursor: the decimal created (1 to MaxTime, no leading zero), a colon, and 64 lowercase hex digits of a txid in display order.
func ParseJSON ¶
ParseJSON parses b as one value of the subset: valid UTF-8, no byte order mark, objects with unique member names, strings with no lone surrogate, integers only (no fraction, exponent, leading zero or minus zero, magnitude at most 2^53 - 1), nesting at most 16, and nothing but white space after the value.
func ParseOutpoint ¶
ParseOutpoint parses an outpoint as the engine writes one: 64 lowercase hex digits of a txid in display order, a dot, and the output index in decimal (0 to 4294967295, no leading zero).
func PushDropScript ¶
PushDropScript is the one canonical lock-before PushDrop for key, fields and an optional field signature (bcommon pushdrop.Script).
func RFC3339 ¶
RFC3339 writes t as the one form this contract admits for created: YYYY-MM-DDTHH:MM:SSZ.
func Seal ¶
func Seal(ctx context.Context, w Signer, originator string, doc *Object, brc78 []byte) ([]byte, error)
Seal completes a BRC-169 envelope for the sender: it sets payment to null, the content member to the BRC-78 message in standard base64, and the signature member to the wallet's signature, under the sender's key for [1, "bbox message"] and key id "signature", over SHA-256 of the RFC 8785 serialization without content and signature. It returns the carried bytes: the canonical serialization of the whole envelope.
func SealEnvelope ¶
func SealEnvelope(ctx context.Context, w Sealer, originator string, from, to, plaintext []byte, created uint64) ([]byte, error)
SealEnvelope encrypts the plaintext to the recipient under BRC-78 through the sender's wallet (protocol [2, "message encryption"], a random key id) and completes and signs the BRC-169 envelope (spec section 4). from is the sender's identity key, the wallet's own, and to the recipient's. It returns the content an envelope record carries (key 7).
Example ¶
An envelope from sealing to opening: the sender seals the plaintext into the content, the record carries it, and the recipient checks the content against the record, decrypts it and applies the plaintext's rules.
package main
import (
"bytes"
"context"
"fmt"
ec "github.com/bsv-blockchain/go-sdk/primitives/ec"
"github.com/bsv-blockchain/go-sdk/wallet"
"github.com/lightwebinc/bbox/boxrec"
)
func main() {
ctx := context.Background()
senderKey, _ := ec.NewPrivateKey()
recipientKey, _ := ec.NewPrivateKey()
sender, _ := wallet.NewCompletedProtoWallet(senderKey)
recipient, _ := wallet.NewCompletedProtoWallet(recipientKey)
from, to := senderKey.PubKey().Compressed(), recipientKey.PubKey().Compressed()
doc := &boxrec.Object{}
doc.Set(boxrec.PlainBody, "hello")
plain, err := boxrec.EncodePlaintext(doc)
if err != nil {
panic(err)
}
const created = 1700000000
content, err := boxrec.SealEnvelope(ctx, sender, "example", from, to, plain, created)
if err != nil {
panic(err)
}
env := &boxrec.Envelope{Office: "example_abcdefghij", To: to, Box: "inbox", From: from, Created: created, Content: content}
record, err := env.Encode()
if err != nil {
panic(err)
}
got, err := boxrec.DecodeEnvelope(record)
if err != nil {
panic(err)
}
c, err := boxrec.CheckContent(got)
if err != nil {
panic(err)
}
opened, err := boxrec.Open(ctx, recipient, "example", c, got.From)
if err != nil {
panic(err)
}
p, err := boxrec.ParsePlaintext(opened)
if err != nil {
panic(err)
}
fmt.Println(got.Box, bytes.Equal(got.From, from), *p.Body)
}
Output: inbox true hello
func SplitOffice ¶
SplitOffice returns an office identifier's readable part and suffix. The readable part alone never identifies an office.
func StrictSignature ¶
StrictSignature reports whether der is a strict DER ECDSA signature (BIP 66) with R in [1, n-1] and S in [1, n/2]: the one encoding of a signature a host accepts, so nobody can re-encode it into another byte string that still verifies.
Types ¶
type Admission ¶
type Admission struct {
Kind TxKind
// Txid is the transaction's txid, hash byte order.
Txid [32]byte
// Outputs are the output indices admitted.
Outputs []int
// Retain are the input indices that spend an output the topic holds:
// every one is retained, so no admitted output is deleted when
// something spends it.
Retain []int
// Carrier is set for TxEnvelope and TxReceipt.
Carrier *Carrier
// Spent is, for TxSweep, every outpoint the sweep's inputs spend.
Spent []transaction.Outpoint
}
Admission is what a host admits from one transaction: the outputs to admit and the held inputs to retain (BRC-22's admittance instructions), and what the lookup service records.
func Admit ¶
Admit applies docs/spec.md section 8.1 to one submission: the BEEF as it arrived, and held, the indices of its subject's inputs that spend an output the topic holds (BRC-22's previous coins, as the engine hands them to the topic manager). A carrier's funding output is read from the carrier's own BEEF; no other verdict reads anything but the transaction, its BEEF and the headers, except that a transaction claiming nothing that is not a sweep is accepted only when held names an input. SPV of the BEEF is the engine's and is assumed to have run.
Every refusal is an error: a topic manager raises it rather than answer with empty instructions, so the engine records nothing for the txid.
type Carrier ¶
type Carrier struct {
// Envelope and Content are set for an envelope carrier, Receipt for a
// receipt carrier.
Envelope *Envelope
Content *Content
Receipt *Receipt
// Owner is the record's from or by, the key the carrier is bound to.
Owner []byte
// Record is the record exactly as carried.
Record []byte
// Commitment is C = txid(K), hash byte order.
Commitment [32]byte
// Funding is the outpoint the carrier spends; a mined spend of it by
// another transaction retracts the carrier.
Funding transaction.Outpoint
}
Carrier is an admitted envelope or receipt carrier.
type Class ¶
type Class struct {
Name string
Members []string // sorted
// Free classes are answered at no price on every conforming host.
Free bool
// Page is the most outputs one answer holds.
Page int
}
Class is one ls_bbox question class: a set of query member names.
type Content ¶
type Content struct {
Doc *Object
// Signed is what the signature covers the SHA-256 of: the RFC 8785
// serialization of Doc without content and signature (BRC-169 section
// 7.2 rule 2).
Signed []byte
// Cipher is the BRC-78 message the content member carries.
Cipher []byte
// Signature is the DER signature the signature member carries.
Signature []byte
}
Content is an envelope record's content, parsed and checked against the record.
func CheckContent ¶
CheckContent applies every content rule in order: ParseContent, then VerifySignature.
func ParseContent ¶
ParseContent applies the content rules short of the signature, in their order: content-json (the bytes are exactly the canonical serialization of a JSON object in the subset), content-shape (the BRC-169 members and their agreement with the record), content-cipher (the BRC-78 message's header names the record's sender and recipient). The record must already have passed DecodeEnvelope or Validate.
func (*Content) VerifySignature ¶
VerifySignature is the content-signature rule: the signature member is lowercase hex of a strict low-S DER signature over SHA-256(Signed) that verifies under the sender's key for [1, "bbox message"], key id "signature", counterparty anyone.
type Decrypter ¶
type Decrypter interface {
Decrypt(ctx context.Context, args wallet.DecryptArgs, originator string) (*wallet.DecryptResult, error)
}
Decrypter is the wallet method Open needs; every wallet.Interface has it.
type Envelope ¶
type Envelope struct {
Office string // key 1, the office identifier <name>_<suffix>
To []byte // key 2, the recipient's identity key
Box string // key 3, the box name
From []byte // key 4, the sender's identity key
Created uint64 // key 5, Unix seconds, the sender's clock
Expires uint64 // key 6, Unix seconds; 0 means none
Content []byte // key 7, the BRC-169 envelope, JSON, as carried
// Extra holds integer keys above 7, preserved verbatim and ignored.
Extra cbor.Map
}
Envelope is one envelope record: the payload of one envelope carrier.
func DecodeEnvelope ¶
DecodeEnvelope parses an envelope record in the refusal order: the bound, canonical CBOR and the map's shape, the key types, the magic, then each defined key in ascending order (missing, type, the key's own rule), then the rule across fields.
type Host ¶
type Host struct {
Office string
Headers chaintracker.ChainTracker
MaxBEEF int
}
Host is what admission needs from the host beyond the object: the topic's office, a chain tracker over the host's own block headers, and the host's BEEF bound (DefaultMaxBEEF when zero).
type KeyGetter ¶
type KeyGetter interface {
GetPublicKey(ctx context.Context, args wallet.GetPublicKeyArgs, originator string) (*wallet.GetPublicKeyResult, error)
}
KeyGetter is the wallet method CheckPayment needs; every wallet.Interface has it.
type Kind ¶
type Kind int
Kind is what a locking script claims to carry.
func ClaimOf ¶
ClaimOf is the admission classifier over raw locking-script bytes (docs/spec.md section 8.1): a script claims a record when it starts with a 33-byte push (0x21 and 33 bytes), then OP_CHECKSIG (0xac), then one push whose data the record's claim prefix begins. Nothing else about the script is read here; the lock rule compares the whole script later.
func ClaimOfField ¶
ClaimOfField is what a PushDrop's first field claims to be: an envelope or a receipt record when it starts with a CBOR definite-length map head, key 0 and that record's magic.
type Object ¶
type Object struct {
Members []Member
}
Object is a JSON object whose member names are unique. Members keep the order they were parsed or added in; serialization sorts them.
type Payment ¶
type Payment struct {
// BEEF is the payment transaction as Atomic BEEF (BRC-95).
BEEF []byte
DerivationPrefix string
Outputs []PaymentOutput
}
Payment is a BRC-29 payment made as BRC-169 section 6.1 describes.
type PaymentOutput ¶
PaymentOutput is one output paid to the recipient.
type Plaintext ¶
Plaintext is what the recipient decrypts: a canonical JSON object in the subset whose members of section 4.5 have their shapes. Doc keeps every member, unknown ones included.
func ParsePlaintext ¶
ParsePlaintext applies the plaintext's rules in order: plaintext-json (the bytes are the canonical serialization of a JSON object in the subset), plaintext-shape (body a string; refs an array of at most MaxRefs well-formed references), payment-shape (payment an object with beef, derivationPrefix and a non-empty outputs array of distinct output indices). Unknown members are kept in Doc and ignored.
type Question ¶
type Question struct {
Class Class
Office string
// Key is the identity key the question is about: to, by or history.
Key []byte
// From is the sender a sender question is about.
From []byte
Box string
// After is the page cursor: created and a txid, display order.
AfterCreated uint64
AfterTxid string
// ReceiptFor is an envelope's txid, display order.
ReceiptFor string
// SpentTxid and SpentVout are the outpoint a sweep question is about,
// txid in display order.
SpentTxid string
SpentVout uint32
}
Question is a validated question.
func ParseQuery ¶
ParseQuery validates a BRC-24 query object as parsed (a member given twice has already taken its last value). It must carry exactly the members of one class, each a string meeting its rule; anything else is refused, never answered empty and never ignored.
type Receipt ¶
type Receipt struct {
Office string // key 1
By []byte // key 2, the acknowledging recipient's identity key
Acks [][32]byte // key 3, envelope commitments, hash byte order, ascending
Created uint64 // key 4, Unix seconds, the recipient's clock
// Extra holds integer keys above 4, preserved verbatim and ignored.
Extra cbor.Map
}
Receipt is one receipt record: the payload of one receipt carrier. It acknowledges envelopes by their commitments.
func DecodeReceipt ¶
DecodeReceipt parses a receipt record in the refusal order.
type Ref ¶
type Ref struct {
URL string
SHA256 [32]byte
Length uint64
// Key is the AES-256 key the referenced bytes are encrypted under, or
// nil when they are not.
Key []byte
}
Ref is a reference to content larger than the bound.
type Sealer ¶
type Sealer interface {
Signer
Encrypt(ctx context.Context, args wallet.EncryptArgs, originator string) (*wallet.EncryptResult, error)
}
Sealer is the two wallet methods SealEnvelope needs; every wallet.Interface has them.
type Signer ¶
type Signer interface {
CreateSignature(ctx context.Context, args wallet.CreateSignatureArgs, originator string) (*wallet.CreateSignatureResult, error)
}
Signer is the one wallet method Seal needs; every wallet.Interface has it.
type TxKind ¶
type TxKind int
TxKind is what an admitted transaction is to the topic.
const ( // TxEnvelope is an envelope carrier: output 0 is admitted. TxEnvelope TxKind = iota + 1 // TxReceipt is a receipt carrier: output 0 is admitted. TxReceipt // TxSweep is a mined sweep, or a published funding tree: output 0 is // admitted and every input's outpoint is recorded. TxSweep // TxSpend admits nothing and retains the held outputs it spends. TxSpend )
The kinds of admitted transaction.