proof

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 22, 2023 License: MIT Imports: 46 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// TaprootAssetsFileSuffix is the main file suffix for the Taproot Asset
	// proof files stored on disk.
	TaprootAssetsFileSuffix = ".assetproof"

	// ProofDirName is the name of the directory we'll use to store our
	// proofs.
	ProofDirName = "proofs"
)
View Source
const (
	PrevOutType          tlv.Type = 0
	BlockHeaderType      tlv.Type = 1
	AnchorTxType         tlv.Type = 2
	TxMerkleProofType    tlv.Type = 3
	AssetLeafType        tlv.Type = 4
	InclusionProofType   tlv.Type = 5
	ExclusionProofsType  tlv.Type = 6
	SplitRootProofType   tlv.Type = 7
	MetaRevealType       tlv.Type = 8
	AdditionalInputsType tlv.Type = 9
	ChallengeWitnessType tlv.Type = 10

	TaprootProofOutputIndexType     tlv.Type = 0
	TaprootProofInternalKeyType     tlv.Type = 1
	TaprootProofCommitmentProofType tlv.Type = 2
	TaprootProofTapscriptProofType  tlv.Type = 3

	// CommitmentProofTapSiblingPreimageType is the type of the TLV record
	// for the CommitmentProof's SiblingPreimage field. It continues the
	// count from where commitment.ProofTaprootAssetProofType left off.
	CommitmentProofTapSiblingPreimageType tlv.Type = 2

	TapscriptProofTapPreimage1 tlv.Type = 0
	TapscriptProofTapPreimage2 tlv.Type = 1
	TapscriptProofBip86        tlv.Type = 2

	MetaRevealEncodingType tlv.Type = 0
	MetaRevealDataType     tlv.Type = 1
)
View Source
const Subsystem = "PROF"

Subsystem defines the logging code for this subsystem.

Variables

View Source
var (
	// ErrProofNotFound is returned when a user attempts to look up a proof
	// based on a Locator, but we can't find it on disk.
	ErrProofNotFound = fmt.Errorf("unable to find proof")

	// ErrInvalidLocatorID is returned when a specified has an invalid
	// asset ID.
	ErrInvalidLocatorID = fmt.Errorf("invalid asset ID locator")

	// ErrInvalidLocatorKey is returned when a specified locator script key
	// is invalid.
	ErrInvalidLocatorKey = fmt.Errorf("invalid script key locator")
)
View Source
var (
	// ErrInvalidChecksum is an error returned when an invalid proof file
	// checksum is detected while deserializing it.
	ErrInvalidChecksum = errors.New("invalid proof file checksum")

	// ErrNoProofAvailable is the error that's returned when a proof is
	// attempted to be fetched from an empty file.
	ErrNoProofAvailable = errors.New("no proof available")
)
View Source
var (
	// ErrInvalidTxMerkleProof is an error returned upon verifying an
	// invalid on-chain transaction merkle proof.
	ErrInvalidTxMerkleProof = errors.New("invalid transaction merkle proof")

	// ErrMissingExclusionProofs is an error returned upon noticing an
	// exclusion proof for a P2TR output is missing.
	ErrMissingExclusionProofs = errors.New("missing exclusion proof(s)")

	// ErrMissingSplitRootProof is an error returned upon noticing an
	// inclusion proof for a split root asset is missing.
	ErrMissingSplitRootProof = errors.New("missing split root proof")

	// ErrNonGenesisAssetWithMetaReveal is an error returned if an asset
	// proof has a meta reveal but isn't itself a genesis asset.
	ErrNonGenesisAssetWithMetaReveal = errors.New("non genesis asset has " +
		"meta reveal")

	// ErrMetaRevealMismatch is an error returned if the hash of the meta
	// reveal doesn't match the actual asset meta hash.
	ErrMetaRevealMismatch = errors.New("meta reveal doesn't match meta " +
		"hash")

	// ErrMetaRevealRequired is an error returned if an asset proof for a
	// genesis asset has a non-zero metahash, but doesn't have a meta
	// reveal.
	ErrMetaRevealRequired = errors.New("meta reveal required")
)
View Source
var (
	// ErrInvalidCommitmentProof is an error returned upon attempting to
	// prove a malformed CommitmentProof.
	ErrInvalidCommitmentProof = errors.New(
		"invalid Taproot Asset commitment proof",
	)
)

Functions

func AddExclusionProofs

func AddExclusionProofs(baseProof *BaseProofParams, packet *psbt.Packet,
	isAnchor func(uint32) bool) error

AddExclusionProofs adds exclusion proofs to the base proof for each P2TR output in the given PSBT that isn't an anchor output itself. To determine which output is the anchor output, the passed isAnchor function should return true for the output index that houses the anchor TX.

func AdditionalInputsDecoder

func AdditionalInputsDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func AdditionalInputsEncoder

func AdditionalInputsEncoder(w io.Writer, val any, buf *[8]byte) error

func AdditionalInputsRecord

func AdditionalInputsRecord(inputs *[]File) tlv.Record

func AnchorTxRecord

func AnchorTxRecord(tx *wire.MsgTx) tlv.Record

func AppendTransition

func AppendTransition(blob Blob, params *TransitionParams,
	headerVerifier HeaderVerifier) (Blob, *Proof, error)

AppendTransition appends a new proof for a state transition to the given encoded proof file. Because multiple assets can be committed to in the same on-chain output, this function takes the script key of the asset to return the proof for. This method returns both the encoded full provenance (proof chain) and the added latest proof.

func AssetLeafRecord

func AssetLeafRecord(a *asset.Asset) tlv.Record

func BlockHeaderDecoder

func BlockHeaderDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func BlockHeaderEncoder

func BlockHeaderEncoder(w io.Writer, val any, buf *[8]byte) error

func BlockHeaderRecord

func BlockHeaderRecord(header *wire.BlockHeader) tlv.Record

func BoolDecoder

func BoolDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func BoolEncoder

func BoolEncoder(w io.Writer, val any, buf *[8]byte) error

func ChallengeWitnessRecord

func ChallengeWitnessRecord(challengeWitness *wire.TxWitness) tlv.Record

func CommitmentProofDecoder

func CommitmentProofDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func CommitmentProofEncoder

func CommitmentProofEncoder(w io.Writer, val any, buf *[8]byte) error

func CommitmentProofTapSiblingPreimageRecord

func CommitmentProofTapSiblingPreimageRecord(
	preimage **commitment.TapscriptPreimage) tlv.Record

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func ExclusionProofsRecord

func ExclusionProofsRecord(proofs *[]TaprootProof) tlv.Record

func ExtractTaprootKey

func ExtractTaprootKey(tx *wire.MsgTx,
	outputIndex uint32) (*btcec.PublicKey, error)

ExtractTaprootKey attempts to extract a Taproot tweaked key from the output found at `outputIndex`.

func ExtractTaprootKeyFromScript

func ExtractTaprootKeyFromScript(pkScript []byte) (*btcec.PublicKey, error)

ExtractTaprootKeyFromScript attempts to extract a Taproot tweaked key from the given output script.

func InclusionProofRecord

func InclusionProofRecord(proof *TaprootProof) tlv.Record

func MetaRevealDataRecord

func MetaRevealDataRecord(data *[]byte) tlv.Record

func MetaRevealDecoder

func MetaRevealDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func MetaRevealEncoder

func MetaRevealEncoder(w io.Writer, val any, buf *[8]byte) error

func MetaRevealRecord

func MetaRevealRecord(reveal **MetaReveal) tlv.Record

func MetaRevealTypeRecord

func MetaRevealTypeRecord(metaType *MetaType) tlv.Record

func MetaTypeDecoder

func MetaTypeDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func MetaTypeEncoder

func MetaTypeEncoder(w io.Writer, val any, buf *[8]byte) error

func MockHeaderVerifier

func MockHeaderVerifier(blockHeader wire.BlockHeader) error

MockHeaderVerifier is a mock verifier which approves of all block headers.

Header verification usually involves cross-referencing with chain data. Chain data is not available in unit tests. This function is useful for unit tests which are not primarily concerned with block header verification.

func PrevOutRecord

func PrevOutRecord(prevOut *wire.OutPoint) tlv.Record

func SplitRootProofDecoder

func SplitRootProofDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func SplitRootProofEncoder

func SplitRootProofEncoder(w io.Writer, val any, buf *[8]byte) error

func SplitRootProofRecord

func SplitRootProofRecord(proof **TaprootProof) tlv.Record

func TaprootProofCommitmentProofRecord

func TaprootProofCommitmentProofRecord(proof **CommitmentProof) tlv.Record

func TaprootProofDecoder

func TaprootProofDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func TaprootProofEncoder

func TaprootProofEncoder(w io.Writer, val any, buf *[8]byte) error

func TaprootProofInternalKeyRecord

func TaprootProofInternalKeyRecord(internalKey **btcec.PublicKey) tlv.Record

func TaprootProofOutputIndexRecord

func TaprootProofOutputIndexRecord(idx *uint32) tlv.Record

func TaprootProofTapscriptProofRecord

func TaprootProofTapscriptProofRecord(proof **TapscriptProof) tlv.Record

func TaprootProofsDecoder

func TaprootProofsDecoder(r io.Reader, val any, buf *[8]byte, _ uint64) error

func TaprootProofsEncoder

func TaprootProofsEncoder(w io.Writer, val any, buf *[8]byte) error

func TapscriptProofBip86Record

func TapscriptProofBip86Record(bip86 *bool) tlv.Record

func TapscriptProofDecoder

func TapscriptProofDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func TapscriptProofEncoder

func TapscriptProofEncoder(w io.Writer, val any, buf *[8]byte) error

func TapscriptProofTapPreimage1Record

func TapscriptProofTapPreimage1Record(
	preimage **commitment.TapscriptPreimage) tlv.Record

func TapscriptProofTapPreimage2Record

func TapscriptProofTapPreimage2Record(
	preimage **commitment.TapscriptPreimage) tlv.Record

func TxDecoder

func TxDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func TxEncoder

func TxEncoder(w io.Writer, val any, buf *[8]byte) error

func TxMerkleProofDecoder

func TxMerkleProofDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error

func TxMerkleProofEncoder

func TxMerkleProofEncoder(w io.Writer, val any, buf *[8]byte) error

func TxMerkleProofRecord

func TxMerkleProofRecord(proof *TxMerkleProof) tlv.Record

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

Types

type AnnotatedProof

type AnnotatedProof struct {
	Locator

	Blob

	*AssetSnapshot
}

AnnotatedProof an annotated proof contains the raw proof blob along with a locator that may convey additional information related to the proof.

type ApertureHarness added in v0.2.1

type ApertureHarness struct {
	// ListenAddr is the address that the aperture service is listening on.
	ListenAddr string

	// TlsCertPath is the path to the TLS certificate that the aperture
	// service is using.
	TlsCertPath string

	// service is the instance of the aperture service that is running.
	Service *aperture.Aperture
}

ApertureHarness is an integration testing harness for the aperture service.

func NewApertureHarness added in v0.2.1

func NewApertureHarness(t *testing.T, port int) ApertureHarness

NewApertureHarness creates a new instance of the aperture service. It returns a harness which includes useful values for testing.

func (*ApertureHarness) Start added in v0.2.1

func (h *ApertureHarness) Start(errChan chan error) error

Start starts the aperture service.

func (*ApertureHarness) Stop added in v0.2.1

func (h *ApertureHarness) Stop() error

Stop stops the aperture service.

type Archiver

type Archiver interface {
	// FetchProof fetches a proof for an asset uniquely identified by the
	// passed ProofIdentifier.
	//
	// If a proof cannot be found, then ErrProofNotFound should be
	// returned.
	FetchProof(ctx context.Context, id Locator) (Blob, error)

	// ImportProofs attempts to store fully populated proofs on disk. The
	// previous outpoint of the first state transition will be used as the
	// Genesis point. The final resting place of the asset will be used as
	// the script key itself.
	ImportProofs(ctx context.Context, headerVerifier HeaderVerifier,
		proofs ...*AnnotatedProof) error
}

Archiver is the main storage backend the ProofArchiver uses to store and query for proof files.

TODO(roasbeef): other queries like fetching all proofs for a given asset?

type AssetBlobs

type AssetBlobs map[asset.SerializedKey]Blob

AssetBlobs is a data structure used to pass around the proof files for a set of assets which may have been created in the same batched transaction. This maps the script key of the asset to the serialized proof file blob.

func NewMintingBlobs

func NewMintingBlobs(params *MintParams,
	headerVerifier HeaderVerifier,
	blobOpts ...MintingBlobOption) (AssetBlobs, error)

NewMintingBlobs takes a set of minting parameters, and produces a series of serialized proof files, which proves the creation/existence of each of the assets within the batch.

type AssetSnapshot

type AssetSnapshot struct {
	// Asset is the resulting asset of a valid proof.
	Asset *asset.Asset

	// OutPoint is the outpoint that commits to the asset specified above.
	OutPoint wire.OutPoint

	// AnchorBlockHash is the block hash that anchors the Bitcoin
	// transaction for this Taproot Asset state transition.
	AnchorBlockHash chainhash.Hash

	// AnchorBlockHeight is the height of the block hash above.
	AnchorBlockHeight uint32

	// AnchorTxIndex is the transaction index within the above block where
	// the AnchorTx can be found.
	AnchorTxIndex uint32

	// AnchorTx is the transaction that commits to the above asset.
	AnchorTx *wire.MsgTx

	// OutputIndex is the output index in the above transaction that
	// commits to the output.
	OutputIndex uint32

	// InternalKey is the internal key used to commit to the above asset in
	// the AnchorTx.
	InternalKey *btcec.PublicKey

	// ScriptRoot is the Taproot Asset commitment root committed to using
	// the above internal key in the Anchor transaction.
	ScriptRoot *commitment.TapCommitment

	// TapscriptSibling is the pre-image to the tapscript hash of the
	// sibling to the Taproot Asset root. If this is nil then it means the
	// Taproot Asset root is the only tapscript leaf in the tree.
	TapscriptSibling *commitment.TapscriptPreimage

	// SplitAsset is the optional indicator that the asset in the snapshot
	// resulted from splitting an asset. If this is true then the root asset
	// of the split can be found in the asset witness' split commitment.
	SplitAsset bool

	// MetaReveal is the pre-image to the meta data hash of the above
	// asset. This is only populated if the asset is a genesis asset, and
	// the proof had a valid meta reveal.
	MetaReveal *MetaReveal
}

AssetSnapshot commits to the result of a valid proof within a proof file. This represents the state of an asset's lineage at a given point in time.

type BackoffCfg

type BackoffCfg struct {
	// BackoffResetWait is the amount of time we'll wait before
	// resetting the backoff counter to its initial state.
	BackoffResetWait time.Duration `long:"backoffresetwait" description:"The amount of time to wait before resetting the backoff counter."`

	// NumTries is the number of times we'll try to deliver the proof to the
	// receiver before the BackoffResetWait delay is enforced.
	NumTries int `long:"numtries" description:"The number of proof delivery attempts before the backoff counter is reset."`

	// InitialBackoff is the initial backoff time we'll use to wait before
	// retrying to deliver the proof to the receiver.
	InitialBackoff time.Duration `long:"initialbackoff" description:"The initial backoff time to wait before retrying to deliver the proof to the receiver."`

	// MaxBackoff is the maximum backoff time we'll use to wait before
	// retrying to deliver the proof to the receiver.
	MaxBackoff time.Duration `long:"maxbackoff" description:"The maximum backoff time to wait before retrying to deliver the proof to the receiver."`
}

BackoffCfg configures the behaviour of the proof delivery backoff procedure.

type BackoffExecError

type BackoffExecError struct {
	// contains filtered or unexported fields
}

BackoffExecError is an error returned when the backoff execution fails. This error wraps the underlying error returned by the execution function. It allows the porter to determine whether the state machine should be halted or not.

func (*BackoffExecError) Error

func (e *BackoffExecError) Error() string

type BaseProofParams

type BaseProofParams struct {
	// Block is the block that mined the transaction that minted the
	// specified assets.
	Block *wire.MsgBlock

	// Tx is the transaction that created the assets.
	Tx *wire.MsgTx

	// TxIndex is the index of the transaction within the block above.
	TxIndex int

	// OutputIndex is the index of the output in the above transaction that
	// holds the asset commitment.
	OutputIndex int

	// InternalKey is the internal key used to derive the taproot output
	// key in the above transaction.
	InternalKey *btcec.PublicKey

	// TaprootAssetRoot is the asset root that commits to all assets created
	// in the above transaction.
	TaprootAssetRoot *commitment.TapCommitment

	// TapscriptSibling is the pre-image to the tapscript hash of the
	// sibling to the Taproot Asset root. If this is nil then it means the
	// Taproot Asset root is the only tapscript leaf in the tree.
	TapscriptSibling *commitment.TapscriptPreimage

	// ExclusionProofs is the set of TaprootProofs proving the exclusion of
	// any assets from all other Taproot outputs within Tx.
	ExclusionProofs []TaprootProof
}

BaseProofParams holds the set of chain level information needed to create a proof.

func (*BaseProofParams) HaveExclusionProof

func (p *BaseProofParams) HaveExclusionProof(anchorOutputIndex uint32) bool

HaveExclusionProof returns true if the set of exclusion proofs already contains a proof for the given anchor output index.

type BaseVerifier

type BaseVerifier struct {
}

BaseVerifier implements a simple verifier that loads the entire proof file into memory and then verifies it all at once.

func (*BaseVerifier) Verify

func (b *BaseVerifier) Verify(ctx context.Context, blobReader io.Reader,
	headerVerifier HeaderVerifier) (*AssetSnapshot, error)

Verify takes the passed serialized proof file, and returns a nil error if the proof file is valid. A valid file should return an AssetSnapshot of the final state transition of the file.

type Blob

type Blob []byte

Blob represents a serialized proof file, including the checksum.

type CommitmentProof

type CommitmentProof struct {
	commitment.Proof

	// TapSiblingPreimage is an optional preimage of a tap node used to
	// hash together with the Taproot Asset commitment leaf node to arrive
	// at the tapscript root of the expected output.
	TapSiblingPreimage *commitment.TapscriptPreimage
}

CommitmentProof represents a full commitment proof for an asset. It can either prove inclusion or exclusion of an asset within a Taproot Asset commitment.

func (*CommitmentProof) Decode

func (p *CommitmentProof) Decode(r io.Reader) error

Decode attempts to decode the CommitmentProof from the passed io.Reader.

func (*CommitmentProof) DecodeRecords

func (p *CommitmentProof) DecodeRecords() []tlv.Record

DecodeRecords returns the decoding records for the CommitmentProof.

func (CommitmentProof) Encode

func (p CommitmentProof) Encode(w io.Writer) error

Encode attempts to encode the CommitmentProof into the passed io.Writer.

func (CommitmentProof) EncodeRecords

func (p CommitmentProof) EncodeRecords() []tlv.Record

EncodeRecords returns the encoding records for the CommitmentProof.

type Courier

type Courier[Addr any] interface {
	// DeliverProof attempts to delivery a proof to the receiver, using the
	// information in the Addr type.
	DeliverProof(context.Context, Addr, *AnnotatedProof) error

	// ReceiveProof attempts to obtain a proof as identified by the passed
	// locator from the source encapsulated within the specified address.
	ReceiveProof(context.Context, Addr, Locator) (*AnnotatedProof, error)

	// SetSubscribers sets the set of subscribers that will be notified
	// of proof courier related events.
	SetSubscribers(map[uint64]*fn.EventReceiver[fn.Event])
}

Courier abstracts away from the final proof retrieval/delivery process as part of the non-interactive send flow. A sender can use this given the abstracted Addr/source type to send a proof to the receiver. Conversely, a receiver can use this to fetch a proof from the sender.

TODO(roasbeef): FileSystemCourier, RpcCourier

type CourierHarness added in v0.2.1

type CourierHarness interface {
	// Start starts the proof courier service.
	Start(chan error) error

	// Stop stops the proof courier service.
	Stop() error
}

CourierHarness interface is an integration testing harness for a proof courier service.

type CourierType added in v0.2.1

type CourierType int64

CourierType is an enum that represents the different types of proof courier services.

const (
	// DisabledCourier is the default courier type that is used when no
	// courier is specified.
	DisabledCourier CourierType = iota

	// ApertureCourier is a courier that uses the hashmail protocol to
	// deliver proofs.
	ApertureCourier
)

type DeliveryLog

type DeliveryLog interface {
	// StoreProofDeliveryAttempt logs a proof delivery attempt to disk.
	StoreProofDeliveryAttempt(context.Context, Locator) error

	// QueryProofDeliveryLog returns timestamps which correspond to logged
	// proof delivery attempts.
	QueryProofDeliveryLog(context.Context, Locator) ([]time.Time, error)
}

DeliveryLog is an interface that allows the courier to log the (attempted) delivery of a proof.

type File

type File struct {
	// Version is the version of the proof file.
	Version Version
	// contains filtered or unexported fields
}

File represents a proof file comprised of proofs for all of an asset's state transitions back to its genesis state.

func NewEmptyFile

func NewEmptyFile(v Version) *File

NewEmptyFile returns a new empty file with the given version.

func NewFile

func NewFile(v Version, proofs ...Proof) (*File, error)

NewFile returns a new proof file given a version and a series of state transition proofs.

func (*File) AppendProof

func (f *File) AppendProof(proof Proof) error

AppendProof appends a proof to the file and calculates its chained hash.

func (*File) Decode

func (f *File) Decode(r io.Reader) error

Decode decodes a proof file from `r`.

func (*File) Encode

func (f *File) Encode(w io.Writer) error

Encode encodes the proof file into `w` including its checksum.

func (*File) IsEmpty

func (f *File) IsEmpty() bool

IsEmpty returns true if the file does not contain any proofs.

func (*File) LastProof

func (f *File) LastProof() (*Proof, error)

LastProof returns the last proof in the chain of proofs. If the file is empty, this return nil.

func (*File) NumProofs

func (f *File) NumProofs() int

NumProofs returns the number of proofs contained in this file.

func (*File) ProofAt

func (f *File) ProofAt(index uint32) (*Proof, error)

ProofAt returns the proof at the given index. If the file is empty, this returns nil.

func (*File) RawLastProof

func (f *File) RawLastProof() ([]byte, error)

RawLastProof returns the raw last proof in the chain of proofs as a byte slice. If the file is empty, this return nil.

func (*File) RawProofAt

func (f *File) RawProofAt(index uint32) ([]byte, error)

RawProofAt returns the raw proof at the given index as a byte slice. If the file is empty, this returns nil.

func (*File) ReplaceLastProof

func (f *File) ReplaceLastProof(proof Proof) error

ReplaceLastProof attempts to replace the last proof in the file with another one, updating its chained hash in the process.

func (*File) Verify

func (f *File) Verify(ctx context.Context, headerVerifier HeaderVerifier) (
	*AssetSnapshot, error)

Verify attempts to verify a full proof file starting from the asset's genesis.

The passed context can be used to exit early from the inner proof verification loop.

TODO(roasbeef): pass in the expected genesis point here?

type FileArchiver

type FileArchiver struct {
	// contains filtered or unexported fields
}

FileArchiver implements proof Archiver backed by an on-disk file system. The archiver takes a single root directory then creates the following overlap mapping:

proofs/ ├─ asset_id1/ │ ├─ script_key1 │ ├─ script_key2

func NewFileArchiver

func NewFileArchiver(dirName string) (*FileArchiver, error)

NewFileArchiver creates a new file archive rooted at the passed specified directory.

TODO(roasbeef): use fs.FS instead?

TODO(roasbeef): option to memory map these instead? then don't need to lug around large blobs in user space as much

func (*FileArchiver) FetchProof

func (f *FileArchiver) FetchProof(_ context.Context, id Locator) (Blob, error)

FetchProof fetches a proof for an asset uniquely identified by the passed ProofIdentifier.

If a proof cannot be found, then ErrProofNotFound should be returned.

NOTE: This implements the Archiver interface.

func (*FileArchiver) ImportProofs

func (f *FileArchiver) ImportProofs(_ context.Context,
	_ HeaderVerifier, proofs ...*AnnotatedProof) error

ImportProofs attempts to store fully populated proofs on disk. The previous outpoint of the first state transition will be used as the Genesis point. The final resting place of the asset will be used as the script key itself.

NOTE: This implements the Archiver interface.

func (*FileArchiver) RegisterSubscriber

func (f *FileArchiver) RegisterSubscriber(
	receiver *fn.EventReceiver[Blob],
	deliverExisting bool, deliverFrom []*Locator) error

RegisterSubscriber adds a new subscriber for receiving events. The deliverExisting boolean indicates whether already existing items should be sent to the NewItemCreated channel when the subscription is started. An optional deliverFrom can be specified to indicate from which timestamp/index/ marker onward existing items should be delivered on startup. If deliverFrom is nil/zero/empty then all existing items will be delivered.

func (*FileArchiver) RemoveSubscriber

func (f *FileArchiver) RemoveSubscriber(
	subscriber *fn.EventReceiver[Blob]) error

RemoveSubscriber removes the given subscriber and also stops it from processing events.

type HashMailBox

type HashMailBox struct {
	// contains filtered or unexported fields
}

HashMailBox is an implementation of the ProofMailbox interface backed by the hashmailrpc.HashMailClient.

func NewHashMailBox

func NewHashMailBox(serverAddr string,
	tlsCertPath string) (*HashMailBox, error)

NewHashMailBox makes a new mailbox by dialing to the server specified by the address above.

NOTE: The TLS certificate path argument (tlsCertPath) is optional. If unset, then the system's TLS trust store is used.

func (*HashMailBox) AckProof

func (h *HashMailBox) AckProof(ctx context.Context, sid streamID) error

AckProof sends an ACK from the receiver to the sender that a proof has been received.

func (*HashMailBox) CleanUp

func (h *HashMailBox) CleanUp(ctx context.Context, sid streamID) error

CleanUp atempts to tear down the mailbox as specified by the passed sid.

func (*HashMailBox) Init

func (h *HashMailBox) Init(ctx context.Context, sid streamID) error

Init creates a mailbox given the specified stream ID.

func (*HashMailBox) ReadProof

func (h *HashMailBox) ReadProof(ctx context.Context,
	sid streamID) (Blob, error)

ReadProof reads a proof from the mailbox. This is a blocking method.

func (*HashMailBox) RecvAck

func (h *HashMailBox) RecvAck(ctx context.Context, sid streamID) error

RecvAck waits for the sender to receive the ack from the receiver.

func (*HashMailBox) WriteProof

func (h *HashMailBox) WriteProof(ctx context.Context, sid streamID,
	proof Blob) error

WriteProof writes the proof to the mailbox specified by the sid.

type HashMailCourier

type HashMailCourier struct {
	// contains filtered or unexported fields
}

HashMailCourier is an implementation of the Courier interfaces that

func NewHashMailCourier

func NewHashMailCourier(cfg *HashMailCourierCfg, mailbox ProofMailbox,
	deliveryLog DeliveryLog) (*HashMailCourier, error)

NewHashMailCourier implements the Courier interface using the specified ProofMailbox. This instance of the Courier relies on the Taproot Asset address itself as the parametrized address type.

func (*HashMailCourier) DeliverProof

func (h *HashMailCourier) DeliverProof(ctx context.Context, recipient Recipient,
	proof *AnnotatedProof) error

DeliverProof attempts to delivery a proof to the receiver, using the information in the Addr type.

TODO(roasbeef): other delivery context as type param?

func (*HashMailCourier) ReceiveProof

func (h *HashMailCourier) ReceiveProof(ctx context.Context, recipient Recipient,
	loc Locator) (*AnnotatedProof, error)

ReceiveProof attempts to obtain a proof as identified by the passed locator from the source encapsulated within the specified address.

func (*HashMailCourier) SetSubscribers

func (h *HashMailCourier) SetSubscribers(
	subscribers map[uint64]*fn.EventReceiver[fn.Event])

SetSubscribers sets the subscribers for the courier. This method is thread-safe.

type HashMailCourierCfg

type HashMailCourierCfg struct {
	Addr string `long:"addr" description:"The full host:port of the hashmail service which is used to deliver proofs"`

	TlsCertPath string `long:"tlscertpath" description:"Service TLS certificate file path"`

	// ReceiverAckTimeout is the maximum time we'll wait for the receiver to
	// acknowledge the proof.
	ReceiverAckTimeout time.Duration `long:"receiveracktimeout" description:"The maximum time to wait for the receiver to acknowledge the proof."`

	// BackoffCfg configures the behaviour of the proof delivery
	// functionality.
	BackoffCfg *BackoffCfg
}

HashMailCourierCfg is the config for the hashmail proof courier.

type HeaderVerifier

type HeaderVerifier func(blockHeader wire.BlockHeader) error

HeaderVerifier is a callback function which returns an error if the given block header is invalid (usually: not present on chain).

type Locator

type Locator struct {
	// AssetID the asset ID of the proof to fetch. This is an optional field.
	AssetID *asset.ID

	// GroupKey the group key of the asset to fetch. This is an optional
	// field.
	GroupKey *btcec.PublicKey

	// ScriptKey specifies the script key of the asset to fetch/store. This
	// field MUST be specified.
	ScriptKey btcec.PublicKey
}

Locator is able to uniquely identify a proof in the extended Taproot Asset Universe by a combination of the: top-level asset ID, the group key, and also the script key.

func (*Locator) Hash

func (l *Locator) Hash() [32]byte

Hash returns a SHA256 hash of the bytes serialized locator.

type MetaReveal

type MetaReveal struct {
	// Type is the type of the metadata.
	Type MetaType

	// Data is the committed data being revealed.
	Data []byte
}

MetaReveals is an optional TLV type that can be added to the proof of a genesis asset to reveal pre-image to the metadata hash. If present, then the following equality must hold for the genesis proof to be valid:

  • sha256(tlvEncode(metaReveal)) == metaHash

func (*MetaReveal) Decode

func (m *MetaReveal) Decode(r io.Reader) error

Decode decodes the meta reveal from the given reader.

func (*MetaReveal) DecodeRecords

func (m *MetaReveal) DecodeRecords() []tlv.Record

DecodeRecords returns the TLV decode records for the meta reveal.

func (*MetaReveal) Encode

func (m *MetaReveal) Encode(w io.Writer) error

Encode encodes the meta reveal to the given writer.

func (*MetaReveal) EncodeRecords

func (m *MetaReveal) EncodeRecords() []tlv.Record

EncodeRecords returns the TLV encode records for the meta reveal.

func (*MetaReveal) MetaHash

func (m *MetaReveal) MetaHash() [asset.MetaHashLen]byte

MetaHash returns the computed meta hash based on the TLV serialization of the meta data itself.

type MetaType

type MetaType uint8

MetaType is the type of the meta data being revealed.

const (
	// MetaOpaque signals that the meta data is simply a set of opaque
	// bytes without any specific interpretation.
	MetaOpaque MetaType = 1
)

type MintParams

type MintParams struct {
	// BaseProofParams houses the basic chain level parameters needed to
	// construct a proof.
	BaseProofParams

	// GenesisPoint is the genesis outpoint (first spent outpoint in the
	// transaction above).
	GenesisPoint wire.OutPoint
}

MintParams holds the set of chain level information needed to make a proof file for the set of assets minted in a batch.

type MintingBlobOption

type MintingBlobOption func(*mintingBlobOpts)

MintingBlobOption allows the caller to modify how the final set of minting blobs is created. This can be used to attach optional data to the proof file.

func WithAssetMetaReveals

func WithAssetMetaReveals(
	metaReveals map[asset.SerializedKey]*MetaReveal) MintingBlobOption

WithAssetMetaReveals is a MintingBlobOption that allows the caller to attach meta reveal information to the initial minting blob created.

type MockVerifier

type MockVerifier struct {
	// contains filtered or unexported fields
}

func NewMockVerifier

func NewMockVerifier(t *testing.T) *MockVerifier

func (*MockVerifier) Verify

func (m *MockVerifier) Verify(_ context.Context, _ io.Reader,
	headerVerifier HeaderVerifier) (*AssetSnapshot, error)

type MultiArchiver

type MultiArchiver struct {
	// contains filtered or unexported fields
}

MultiArchiver is an archive of archives. It contains several archives and attempts to use them either as a look-aside cache, or a write through cache for all incoming requests.

func NewMultiArchiver

func NewMultiArchiver(verifier Verifier, archiveTimeout time.Duration,
	backends ...Archiver) *MultiArchiver

NewMultiArchiver creates a new MultiArchiver based on the set of specified backends.

func (*MultiArchiver) FetchProof

func (m *MultiArchiver) FetchProof(ctx context.Context,
	loc Locator) (Blob, error)

FetchProof fetches a proof for an asset uniquely identified by the passed ProofIdentifier.

func (*MultiArchiver) ImportProofs

func (m *MultiArchiver) ImportProofs(ctx context.Context,
	headerVerifier HeaderVerifier, proofs ...*AnnotatedProof) error

ImportProofs attempts to store fully populated proofs on disk. The previous outpoint of the first state transition will be used as the Genesis point. The final resting place of the asset will be used as the script key itself.

func (*MultiArchiver) RegisterSubscriber

func (m *MultiArchiver) RegisterSubscriber(receiver *fn.EventReceiver[Blob],
	deliverExisting bool, deliverFrom []*Locator) error

RegisterSubscriber adds a new subscriber for receiving events. The deliverExisting boolean indicates whether already existing items should be sent to the NewItemCreated channel when the subscription is started. An optional deliverFrom can be specified to indicate from which timestamp/index/ marker onward existing items should be delivered on startup. If deliverFrom is nil/zero/empty then all existing items will be delivered.

func (*MultiArchiver) RemoveSubscriber

func (m *MultiArchiver) RemoveSubscriber(
	subscriber *fn.EventReceiver[Blob]) error

RemoveSubscriber removes the given subscriber and also stops it from processing events.

type NotifyArchiver

type NotifyArchiver interface {
	Archiver

	fn.EventPublisher[Blob, []*Locator]
}

NotifyArchiver is an Archiver that also allows callers to subscribe to notifications about new proofs being added to the archiver.

type Proof

type Proof struct {
	// PrevOut is the previous on-chain outpoint of the asset.
	PrevOut wire.OutPoint

	// BlockHeader is the current block header committing to the on-chain
	// transaction attempting an asset state transition.
	BlockHeader wire.BlockHeader

	// AnchorTx is the on-chain transaction attempting the asset state
	// transition.
	AnchorTx wire.MsgTx

	// TxMerkleProof is the merkle proof for AnchorTx used to prove its
	// inclusion within BlockHeader.
	//
	// TODO(roasbeef): also store height+index information?
	TxMerkleProof TxMerkleProof

	// Asset is the resulting asset after its state transition.
	Asset asset.Asset

	// InclusionProof is the TaprootProof proving the new inclusion of the
	// resulting asset within AnchorTx.
	InclusionProof TaprootProof

	// ExclusionProofs is the set of TaprootProofs proving the exclusion of
	// the resulting asset from all other Taproot outputs within AnchorTx.
	ExclusionProofs []TaprootProof

	// SplitRootProof is an optional TaprootProof needed if this asset is
	// the result of a split. SplitRootProof proves inclusion of the root
	// asset of the split.
	SplitRootProof *TaprootProof

	// MetaReveal is the set of bytes that were revealed to prove the
	// derivation of the meta data hash contained in the genesis asset.
	//
	// TODO(roasbeef): use even/odd framing here?
	//
	// NOTE: This field is optional, and can only be specified if the asset
	// above is a genesis asset. If specified, then verifiers _should_ also
	// verify the hashes match up.
	MetaReveal *MetaReveal

	// AdditionalInputs is a nested full proof for any additional inputs
	// found within the resulting asset.
	AdditionalInputs []File

	// ChallengeWitness is an optional virtual transaction witness that
	// serves as an ownership proof for the asset. If this is non-nil, then
	// it is a valid transfer witness for a 1-input, 1-output virtual
	// transaction that spends the asset in this proof and sends it to the
	// NUMS key, to prove that the creator of the proof is able to produce
	// a valid signature to spend the asset.
	ChallengeWitness wire.TxWitness
}

Proof encodes all of the data necessary to prove a valid state transition for an asset has occurred within an on-chain transaction.

func CreateTransitionProof

func CreateTransitionProof(prevOut wire.OutPoint,
	params *TransitionParams) (*Proof, error)

CreateTransitionProof creates a proof for an asset transition, based on the last proof of the last asset state and the new asset in the params.

func (*Proof) Decode

func (p *Proof) Decode(r io.Reader) error

Decode decodes a Proof from `r`.

func (*Proof) DecodeRecords

func (p *Proof) DecodeRecords() []tlv.Record

DecodeRecords returns the set of known TLV records to decode a Proof.

func (*Proof) Encode

func (p *Proof) Encode(w io.Writer) error

Encode encodes a Proof into `w`.

func (*Proof) EncodeRecords

func (p *Proof) EncodeRecords() []tlv.Record

EncodeRecords returns the set of known TLV records to encode a Proof.

func (*Proof) UpdateTransitionProof

func (p *Proof) UpdateTransitionProof(params *BaseProofParams) error

UpdateTransitionProof computes a new transaction merkle proof from the given proof parameters, and updates a proof to be anchored at the given anchor transaction. This is needed to reflect confirmation of an anchor transaction.

func (*Proof) Verify

func (p *Proof) Verify(ctx context.Context, prev *AssetSnapshot,
	headerVerifier HeaderVerifier) (*AssetSnapshot, error)

Verify verifies the proof by ensuring that:

  1. A transaction that spends the previous asset output has a valid merkle proof within a block in the chain.
  2. A valid inclusion proof for the resulting asset is included.
  3. A valid inclusion proof for the split root, if the resulting asset is a split asset.
  4. A set of valid exclusion proofs for the resulting asset are included.
  5. A set of asset inputs with valid witnesses are included that satisfy the resulting state transition.

type ProofMailbox

type ProofMailbox interface {
	// Init creates a mailbox given the specified stream ID.
	Init(ctx context.Context, sid streamID) error

	// WriteProof writes the proof to the mailbox specified by the sid.
	WriteProof(ctx context.Context, sid streamID, proof Blob) error

	// ReadProof reads a proof from the mailbox. This is a blocking method.
	ReadProof(ctx context.Context, sid streamID) (Blob, error)

	// AckProof sends an ACK from the receiver to the sender that a proof
	// has been received.
	AckProof(ctx context.Context, sid streamID) error

	// RecvAck waits for the sender to receive the ack from the receiver.
	RecvAck(ctx context.Context, sid streamID) error

	// CleanUp attempts to tear down the mailbox as specified by the passed
	// sid.
	CleanUp(ctx context.Context, sid streamID) error
}

ProofMailbox represents an abstract store-and-forward mailbox that can be used to send/receive proofs.

type ReceiverProofBackoffWaitEvent

type ReceiverProofBackoffWaitEvent struct {

	// Backoff is the current Backoff duration.
	Backoff time.Duration

	// TriesCounter is the number of tries we've made so far during the
	// course of the current Backoff procedure to deliver the proof to the
	// receiver.
	TriesCounter int64
	// contains filtered or unexported fields
}

ReceiverProofBackoffWaitEvent is an event that is sent to a subscriber each time we wait via the Backoff procedure before retrying to deliver a proof to the receiver.

func NewReceiverProofBackoffWaitEvent

func NewReceiverProofBackoffWaitEvent(
	backoff time.Duration, triesCounter int64) *ReceiverProofBackoffWaitEvent

NewReceiverProofBackoffWaitEvent creates a new ReceiverProofBackoffWaitEvent.

func (*ReceiverProofBackoffWaitEvent) Timestamp

func (e *ReceiverProofBackoffWaitEvent) Timestamp() time.Time

Timestamp returns the timestamp of the event.

type Recipient

type Recipient struct {
	// ScriptKey is the main identifier of the recipient. It is used to
	// derive the stream IDs for the mailbox.
	ScriptKey *btcec.PublicKey

	// AssetID is the ID of the asset that is being transferred. This is
	// used for logging purposes only.
	AssetID asset.ID

	// Amount is the amount of the asset that is being transferred. This is
	// used for logging purposes only.
	Amount uint64
}

Recipient describes the recipient of a proof. The script key is enough to identify a transferred asset in the context of the proof courier. This is because a proof only needs to be delivered via courier if the recipient used an address to receive (non-interactive). And each address requires the user to derive a fresh and unique script key. The other fields are used for logging purposes only.

type TaprootProof

type TaprootProof struct {
	// OutputIndex is the index of the output for which the proof applies.
	OutputIndex uint32

	// InternalKey is the internal key of the taproot output at OutputIndex.
	InternalKey *btcec.PublicKey

	// CommitmentProof represents a commitment proof for an asset, proving
	// inclusion or exclusion of an asset within a Taproot Asset commitment.
	CommitmentProof *CommitmentProof

	// TapscriptProof represents a taproot control block to prove that a
	// taproot output is not committing to a Taproot Asset commitment.
	//
	// NOTE: This field will be set only if the output does NOT contain a
	// valid Taproot Asset commitment.
	TapscriptProof *TapscriptProof
}

TaprootProof represents a proof that reveals the partial contents to a tapscript tree within a taproot output. It can prove whether an asset is being included/excluded from a Taproot Asset commitment through a CommitmentProof, or that no Taproot Asset commitment exists at all through a TapscriptProof.

func (*TaprootProof) Decode

func (p *TaprootProof) Decode(r io.Reader) error

func (*TaprootProof) DecodeRecords

func (p *TaprootProof) DecodeRecords() []tlv.Record

func (TaprootProof) DeriveByAssetExclusion

func (p TaprootProof) DeriveByAssetExclusion(assetCommitmentKey,
	tapCommitmentKey [32]byte) (*btcec.PublicKey, error)

DeriveByAssetExclusion derives the possible taproot keys backing a Taproot Asset commitment by interpreting the TaprootProof as an asset exclusion proof. Asset exclusion proofs can take two forms: one where an asset proof proves that the asset no longer exists within its AssetCommitment, and another where the AssetCommitment corresponding to the excluded asset no longer exists within the TapCommitment.

There are at most two possible keys to try if each leaf preimage matches the length of a branch preimage. However, based on the type of the sibling pre-image we'll derive just a single version of it.

func (TaprootProof) DeriveByAssetInclusion

func (p TaprootProof) DeriveByAssetInclusion(
	asset *asset.Asset) (*btcec.PublicKey, *commitment.TapCommitment,
	error)

DeriveByAssetInclusion derives the unique taproot output key backing a Taproot Asset commitment by interpreting the TaprootProof as an asset inclusion proof.

There are at most two _possible_ keys that exist if each leaf preimage matches the length of a branch preimage. However, using the annotated type information we only need to derive a single key.

func (TaprootProof) DeriveByTapscriptProof

func (p TaprootProof) DeriveByTapscriptProof() (*btcec.PublicKey, error)

DeriveByTapscriptProof derives the possible taproot keys from a TapscriptProof backing a taproot output that does not include a Taproot Asset commitment.

NOTE: There are at most two possible keys to try if each leaf preimage matches the length of a branch preimage. However, we can derive only the one specified in the contained proof.

func (TaprootProof) Encode

func (p TaprootProof) Encode(w io.Writer) error

func (TaprootProof) EncodeRecords

func (p TaprootProof) EncodeRecords() []tlv.Record

type TapscriptProof

type TapscriptProof struct {
	// TapPreimage1 is the preimage for a TapNode at depth 0 or 1.
	TapPreimage1 *commitment.TapscriptPreimage

	// TapPreimage2, if specified, is the pair preimage for TapPreimage1 at
	// depth 1.
	TapPreimage2 *commitment.TapscriptPreimage

	// Bip86 indicates this is a normal BIP-0086 wallet output (likely a
	// change output) that does not commit to any script or Taproot Asset
	// root.
	Bip86 bool
}

TapscriptProof represents a proof of a Taproot output not including a Taproot Asset commitment. Taproot Asset commitments must exist at a leaf with depth 0 or 1, so we can guarantee that a Taproot Asset commitment doesn't exist by revealing the preimage of one node at depth 0 or two nodes at depth 1.

TODO(roasbeef): make *this* into the control block proof?

func (*TapscriptProof) Decode

func (p *TapscriptProof) Decode(r io.Reader) error

Decode attempts to decode the TapscriptProof to the passed io.Reader.

func (*TapscriptProof) DecodeRecords

func (p *TapscriptProof) DecodeRecords() []tlv.Record

DecodeRecords returns the decoding records for TapscriptProof.

func (TapscriptProof) DeriveTaprootKeys

func (p TapscriptProof) DeriveTaprootKeys(internalKey *btcec.PublicKey) (
	*btcec.PublicKey, error)

DeriveTaprootKeys derives the expected taproot key from a TapscriptProof backing a taproot output that does not include a Taproot Asset commitment.

There are at most two possible keys to try if each leaf preimage matches the length of a branch preimage. However, based on the annotated type information, we only need to derive a single expected key.

func (TapscriptProof) Encode

func (p TapscriptProof) Encode(w io.Writer) error

Encode attempts to encode the TapscriptProof to the passed io.Writer.

func (TapscriptProof) EncodeRecords

func (p TapscriptProof) EncodeRecords() []tlv.Record

EncodeRecords returns the encoding records for TapscriptProof.

type TransitionParams

type TransitionParams struct {
	// BaseProofParams houses the basic chain level parameters needed to
	// construct a proof.
	BaseProofParams

	// NewAsset is the new asset created by the asset transition.
	NewAsset *asset.Asset

	// RootOutputIndex is the index of the output that commits to the split
	// root asset, if present.
	RootOutputIndex uint32

	// RootInternalKey is the internal key of the output at RootOutputIndex.
	RootInternalKey *btcec.PublicKey

	// RootTaprootAssetTree is the commitment root that commitments to the
	// inclusion of the root split asset at the RootOutputIndex.
	RootTaprootAssetTree *commitment.TapCommitment
}

TransitionParams holds the set of chain level information needed to append a proof to an existing file for the given asset state transition.

type TxMerkleProof

type TxMerkleProof struct {
	// Nodes is the list of nodes to hash along with the transaction being
	// proved to arrive at the block's merkle root.
	Nodes []chainhash.Hash

	// Bits indicates the direction for each node found in Nodes above. A
	// 0 bit indicates a left direction or a right direction otherwise.
	Bits []bool
}

TxMerkleProof represents a simplified version of BIP-0037 transaction merkle proofs for a single transaction.

func NewTxMerkleProof

func NewTxMerkleProof(txs []*wire.MsgTx, txIdx int) (*TxMerkleProof, error)

NewTxMerkleProof computes the merkle proof for a specific transaction found within a block's set of transactions.

func (*TxMerkleProof) Decode

func (p *TxMerkleProof) Decode(r io.Reader) error

Decode decodes a TxMerkleProof from `r`.

func (TxMerkleProof) Encode

func (p TxMerkleProof) Encode(w io.Writer) error

Encode encodes a TxMerkleProof into `w`.

func (TxMerkleProof) Verify

func (p TxMerkleProof) Verify(tx *wire.MsgTx, merkleRoot chainhash.Hash) bool

Verify verifies a merkle proof for `tx` by ensuring the end result matches the expected `merkleRoot`.

type Verifier

type Verifier interface {
	// Verify takes the passed serialized proof file, and returns a nil
	// error if the proof file is valid. A valid file should return an
	// AssetSnapshot of the final state transition of the file.
	Verify(c context.Context, blobReader io.Reader,
		headerVerifier HeaderVerifier) (*AssetSnapshot, error)
}

Verifier abstracts away from the task of verifying a proof file blob.

type Version

type Version uint32

Version denotes the versioning scheme for proof files.

const (
	// V0 is the first version of the proof file.
	V0 Version = 0
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL