db

package
v0.6.3 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2023 License: BlueOak-1.0.0 Imports: 9 Imported by: 1

Documentation

Index

Constants

View Source
const (
	ErrGeneralFailure uint16 = iota
	ErrUnknownMatch
	ErrUnknownOrder
	ErrUnsupportedMarket
	ErrInvalidOrder
	ErrReusedCommit
	ErrOrderNotExecuted
	ErrUpdateCount
	ErrAccountExists
	ErrAccountUnknown
	ErrAccountBadFeeInfo
	ErrUnknownFeeKey
)

The possible Code values in an ArchiveError.

View Source
const EpochGapNA int32 = -1

EpochGapNA is a specifier for an epoch gap (epochs between limit order and cancel order) when such a designation doesn't apply in-context. For instance, revocations are treated in many places like cancel orders, but there is no reason to consider the epoch gap.

Variables

This section is empty.

Functions

func IsErrAccountUnknown added in v0.4.0

func IsErrAccountUnknown(err error) bool

IsErrAccountUnknown returns true if the error is of type ArchiveError and has code ErrAccountUnknown.

func IsErrGeneralFailure

func IsErrGeneralFailure(err error) bool

IsErrGeneralFailure returns true if the error is of type ArchiveError and has code ErrGeneralFailure.

func IsErrInvalidOrder

func IsErrInvalidOrder(err error) bool

IsErrInvalidOrder returns true if the error is of type ArchiveError and has code ErrInvalidOrder.

func IsErrMatchUnknown

func IsErrMatchUnknown(err error) bool

IsErrMatchUnknown returns true if the error is of type ArchiveError and has code ErrUnknownMatch.

func IsErrMatchUnsupported

func IsErrMatchUnsupported(err error) bool

IsErrMatchUnsupported returns true if the error is of type ArchiveError and has code ErrUnsupportedMarket.

func IsErrOrderNotExecuted

func IsErrOrderNotExecuted(err error) bool

IsErrOrderNotExecuted returns true if the error is of type ArchiveError and has code ErrOrderNotExecuted.

func IsErrOrderUnknown

func IsErrOrderUnknown(err error) bool

IsErrOrderUnknown returns true if the error is of type ArchiveError and has code ErrUnknownOrder.

func IsErrReusedCommit

func IsErrReusedCommit(err error) bool

IsErrReusedCommit returns true if the error is of type ArchiveError and has code ErrReusedCommit.

func IsErrUnknownFeeKey added in v0.4.0

func IsErrUnknownFeeKey(err error) bool

IsErrUnknownFeeKey returns true if the error is of type ArchiveError and has code ErrUnknownFeeKey.

func IsErrUpdateCount

func IsErrUpdateCount(err error) bool

IsErrUpdateCount returns true if the error is of type ArchiveError and has code ErrUpdateCount.

func Register

func Register(name string, driver Driver)

Register should be called by the init function of an DB driver's package.

func SameErrorTypes

func SameErrorTypes(errA, errB error) bool

SameErrorTypes checks for error equality or ArchiveError.Code equality if both errors are of type ArchiveError.

func UseLogger

func UseLogger(logger dex.Logger)

UseLogger sets the logger to use for all of the DB Drivers.

func ValidateOrder

func ValidateOrder(ord order.Order, status order.OrderStatus, mkt *dex.MarketInfo) bool

ValidateOrder ensures that the order with the given status for the specified market is sensible. This function is in the database package because the concept of a valid order-status-market state is dependent on the semantics of order archival. The ServerTime may not be set yet, so the OrderID cannot be computed.

Types

type Account

type Account struct {
	AccountID  account.AccountID `json:"accountid"`
	Pubkey     dex.Bytes         `json:"pubkey"`
	FeeAsset   uint32            `json:"feeasset"`
	FeeAddress string            `json:"feeaddress"` // DEPRECATED
	FeeCoin    dex.Bytes         `json:"feecoin"`    // DEPRECATED
}

Account holds data returned by Accounts.

type AccountArchiver

type AccountArchiver interface {
	// Account retrieves the account information for the specified account ID. A
	// nil pointer will be returned for unknown or closed accounts. Bond and
	// registration fee payment status is returned as well. A bond is active if
	// its lockTime is after the lockTimeThresh Time, which should be
	// time.Now().Add(bondExpiry). The legacy bool return refers to the legacy
	// registration fee system, and legacyPaid indicates if the account has a
	// recorded fee coin (paid legacy fee).
	Account(acctID account.AccountID, lockTimeThresh time.Time) (acct *account.Account, activeBonds []*Bond, legacy, legacyPaid bool)

	// CreateAccount stores a new account with an assigned registration address
	// for a specific asset. The account is considered unpaid until PayAccount
	// is used to set the payment transaction details. This is intended for use
	// with the old registration fee system, since with the bond system,
	// accounts are not to be created until a bond transaction is created and
	// broadcasted. The account is considered unpaid until PayAccount is used to
	// set the registration fee payment details. (V0PURGE)
	CreateAccount(acct *account.Account, assetID uint32, regAddr string) error

	// CreateAccountWithBond creates a new account with the given bond. This is
	// used for the new postbond request protocol. The bond tx should be
	// fully-confirmed.
	CreateAccountWithBond(acct *account.Account, bond *Bond) error

	// AddBond stores a new Bond, which is uniquely identified by (asset ID,
	// coin ID), for an existing account.
	AddBond(acct account.AccountID, bond *Bond) error

	// DeleteBond deletes a bond which should generally be expired.
	DeleteBond(assetID uint32, coinID []byte) error

	// AccountRegAddr gets any legacy registration fee address and the
	// corresponding asset ID for the account. (V0PURGE)
	AccountRegAddr(account.AccountID) (string, uint32, error)

	// PayAccount sets the registration fee payment transaction details for the
	// account, completing the registration process for old fee system.
	// (V0PURGE)
	PayAccount(account.AccountID, []byte) error

	// Accounts returns data for all accounts.
	Accounts() ([]*Account, error)

	// AccountInfo returns data for an account.
	AccountInfo(account.AccountID) (*Account, error)
}

AccountArchiver is the interface required for storage and retrieval of all account data.

type ArchiveError

type ArchiveError struct {
	Code   uint16
	Detail string
}

ArchiveError is the error type used by archivist for certain recognized errors. Not all returned errors will be of this type.

func (ArchiveError) Error

func (ae ArchiveError) Error() string

type Bond added in v0.6.0

type Bond struct {
	Version  uint16
	AssetID  uint32
	CoinID   []byte
	Amount   int64
	Strength uint32 // Amount / <bond increment at time of acceptance>
	LockTime int64
}

Bond represents a time-locked fidelity bond posted by a user.

type CancelRecord added in v0.6.0

type CancelRecord struct {
	ID        order.OrderID
	TargetID  order.OrderID
	MatchTime int64
	// EpochGap is the number of epochs passed since the targeted trade order
	// was placed, where 0 means canceled in the same epoch, 1 means canceled in
	// the next epoch, etc.
	EpochGap int32
}

CancelRecord is info about a cancel order and when it matched.

type DEXArchivist

type DEXArchivist interface {
	// LastErr should returns any fatal or unexpected error encountered by the
	// archivist backend. This may be used to check if the database had an
	// unrecoverable error (disconnect, etc.).
	LastErr() error

	// Fatal provides select semantics like Context.Done when there is a fatal
	// backend error. Use LastErr to get the error.
	Fatal() <-chan struct{}

	// Close should gracefully shutdown the backend, returning when complete.
	Close() error

	// InsertEpoch stores the results of a newly-processed epoch.
	InsertEpoch(ed *EpochResults) error

	// LastEpochRate gets the EndRate of the last EpochResults inserted for the
	// market. If the database is empty, no error and a rate of zero are
	// returned.
	LastEpochRate(b, q uint32) (uint64, error)

	// LoadEpochStats reads all market epoch history from the database.
	LoadEpochStats(uint32, uint32, []*candles.Cache) error

	OrderArchiver
	AccountArchiver
	KeyIndexer
	MatchArchiver
	SwapArchiver
}

DEXArchivist will be composed of several different interfaces. Starting with OrderArchiver.

func Open

func Open(ctx context.Context, name string, cfg interface{}) (DEXArchivist, error)

Open loads the named DB driver with the provided configuration.

type Driver

type Driver interface {
	Open(ctx context.Context, cfg interface{}) (DEXArchivist, error)
	UseLogger(logger dex.Logger)
}

Driver is the interface required of all DB drivers. Open should create a DEXArchivist and verify connectivity with the asset's chain server.

type EpochResults

type EpochResults struct {
	MktBase, MktQuote uint32
	Idx               int64
	Dur               int64
	MatchTime         int64
	CSum              []byte
	Seed              []byte
	OrdersRevealed    []order.OrderID
	OrdersMissed      []order.OrderID
	MatchVolume       uint64
	QuoteVolume       uint64
	BookBuys          uint64
	BookBuys5         uint64
	BookBuys25        uint64
	BookSells         uint64
	BookSells5        uint64
	BookSells25       uint64
	HighRate          uint64
	LowRate           uint64
	StartRate         uint64
	EndRate           uint64
}

EpochResults represents the outcome of epoch order processing, including preimage collection, and computation of commitment checksum and shuffle seed. MatchTime is the time at which order matching is executed.

type KeyIndexer added in v0.4.0

type KeyIndexer interface {
	KeyIndex(xpub string) (uint32, error)
	SetKeyIndex(idx uint32, xpub string) error
}

KeyIndexer are the functions required to track an extended public key and derived children by index.

type MarketMatchID

type MarketMatchID struct {
	order.MatchID
	Base, Quote uint32 // market
}

MarketMatchID designates a MatchID for a certain market by the market's base-quote asset IDs.

func MatchID

func MatchID(match *order.Match) MarketMatchID

MatchID constructs a MarketMatchID from an order.Match.

type MatchArchiver

type MatchArchiver interface {
	InsertMatch(match *order.Match) error
	MatchByID(mid order.MatchID, base, quote uint32) (*MatchData, error)
	UserMatches(aid account.AccountID, base, quote uint32) ([]*MatchData, error)
	CompletedAndAtFaultMatchStats(aid account.AccountID, lastN int) ([]*MatchOutcome, error)
	ForgiveMatchFail(mid order.MatchID) (bool, error)
	AllActiveUserMatches(aid account.AccountID) ([]*MatchData, error)
	MarketMatches(base, quote uint32) ([]*MatchDataWithCoins, error)
	MarketMatchesStreaming(base, quote uint32, includeInactive bool, N int64, f func(*MatchDataWithCoins) error) (int, error)
	MatchStatuses(aid account.AccountID, base, quote uint32, matchIDs []order.MatchID) ([]*MatchStatus, error)
}

MatchArchiver is the interface required for storage and retrieval of all match data.

type MatchData

type MatchData struct {
	ID        order.MatchID
	Taker     order.OrderID
	TakerAcct account.AccountID
	TakerAddr string
	TakerSell bool
	Maker     order.OrderID
	MakerAcct account.AccountID
	MakerAddr string
	Epoch     order.EpochID
	Quantity  uint64
	Rate      uint64
	BaseRate  uint64
	QuoteRate uint64
	Active    bool              // match negotiation in progress, not yet completed or failed
	Status    order.MatchStatus // note that failed swaps, where Active=false, can have any status
}

MatchData represents an order pair match, but with just the order IDs instead of the full orders. The actual orders may be retrieved by ID.

type MatchDataWithCoins added in v0.2.0

type MatchDataWithCoins struct {
	MatchData
	MakerSwapCoin   []byte
	MakerRedeemCoin []byte
	TakerSwapCoin   []byte
	TakerRedeemCoin []byte
}

MatchDataWithCoins pairs MatchData (embedded) with the encode swap and redeem coin IDs blobs for both maker and taker.

type MatchOutcome

type MatchOutcome struct {
	Status      order.MatchStatus
	ID          order.MatchID
	Fail        bool // taker must reach MatchComplete, maker succeeds at MakerRedeemed
	Time        int64
	Value       uint64
	Base, Quote uint32 // the market
}

MatchOutcome pairs an inactive match's status with a timestamp. In the case of a successful match for the user, this is when their redeem was received. In the case of an at-fault match failure for the user, this corresponds to the time of the previous match action. The previous action times are: match time, swap txn validated times, and initiator redeem validated time. Note that this does not directly correspond to match revocation times where inaction deadline references the time when the swap txns reach the required confirms. These times must match the reference times provided to the auth manager when registering new swap outcomes.

type MatchStatus

type MatchStatus struct {
	ID            order.MatchID
	Status        order.MatchStatus
	MakerContract []byte
	TakerContract []byte
	MakerSwap     []byte
	TakerSwap     []byte
	MakerRedeem   []byte
	TakerRedeem   []byte
	Secret        []byte
	Active        bool
	TakerSell     bool
	IsTaker       bool
	IsMaker       bool
}

MatchStatus is the current status of a match, its known contracts and coin IDs, and its secret, if known.

type OrderArchiver

type OrderArchiver interface {
	// Order retrieves an order with the given OrderID, stored for the market
	// specified by the given base and quote assets.
	Order(oid order.OrderID, base, quote uint32) (order.Order, order.OrderStatus, error)

	// BookOrders returns all book orders for a market.
	BookOrders(base, quote uint32) ([]*order.LimitOrder, error)

	// EpochOrders returns all epoch orders for a market.
	EpochOrders(base, quote uint32) ([]order.Order, error)

	// FlushBook revokes all booked orders for a market.
	FlushBook(base, quote uint32) (sellsRemoved, buysRemoved []order.OrderID, err error)

	// ActiveOrderCoins retrieves a CoinID slice for each active order.
	ActiveOrderCoins(base, quote uint32) (baseCoins, quoteCoins map[order.OrderID][]order.CoinID, err error)

	// UserOrders retrieves all orders for the given account in the market
	// specified by a base and quote asset.
	UserOrders(ctx context.Context, aid account.AccountID, base, quote uint32) ([]order.Order, []order.OrderStatus, error)

	// UserOrderStatuses retrieves the statuses and filled amounts of the orders
	// with the provided order IDs for the given account in the market specified
	// by a base and quote asset.
	// The number and ordering of the returned statuses is not necessarily the
	// same as the number and ordering of the provided order IDs. It is not an
	// error if any or all of the provided order IDs cannot be found for the
	// given account in the specified market.
	UserOrderStatuses(aid account.AccountID, base, quote uint32, oids []order.OrderID) ([]*OrderStatus, error)

	// ActiveUserOrderStatuses retrieves the statuses and filled amounts of all
	// active orders for a user across all markets.
	ActiveUserOrderStatuses(aid account.AccountID) ([]*OrderStatus, error)

	// CompletedUserOrders retrieves the N most recently completed orders for a
	// user across all markets.
	CompletedUserOrders(aid account.AccountID, N int) (oids []order.OrderID, compTimes []int64, err error)

	// PreimageStats retrieves the N most recent results of preimage requests
	// for the user across all markets.
	PreimageStats(user account.AccountID, lastN int) ([]*PreimageResult, error)

	// ExecutedCancelsForUser retrieves up to N executed cancel orders for a
	// given user. These may be user-initiated cancels, or cancels created by
	// the server (revokes). Executed cancel orders from all markets are
	// returned.
	ExecutedCancelsForUser(aid account.AccountID, N int) ([]*CancelRecord, error)

	// OrderWithCommit searches all markets' trade and cancel orders, both
	// active and archived, for an order with the given Commitment.
	OrderWithCommit(ctx context.Context, commit order.Commitment) (found bool, oid order.OrderID, err error)

	// OrderStatus gets the status, ID, and filled amount of the given order.
	OrderStatus(order.Order) (order.OrderStatus, order.OrderType, int64, error)

	// NewEpochOrder stores a new order with epoch status. Such orders are
	// pending execution or insertion on a book (standing limit orders with a
	// remaining unfilled amount). For trade orders, the epoch gap should be
	// db.EpochGapNA, while for cancel orders it is the number of epochs since
	// the targeted order was placed, as described in the docs for CancelRecord.
	NewEpochOrder(ord order.Order, epochIdx, epochDur int64, epochGap int32) error

	// StorePreimage stores the preimage associated with an existing order.
	StorePreimage(ord order.Order, pi order.Preimage) error

	// BookOrder books the given order. If the order was already stored (i.e.
	// NewEpochOrder), it's status and filled amount are updated, otherwise it
	// is inserted. See also UpdateOrderFilled.
	BookOrder(*order.LimitOrder) error

	// ExecuteOrder puts the order into the executed state, and sets the filled
	// amount for market and limit orders. For unmatched cancel orders, use
	// FailCancelOrder instead.
	ExecuteOrder(ord order.Order) error

	// CancelOrder puts a limit order into the canceled state. Market orders
	// must use ExecuteOrder since they may not be canceled. Similarly, cancel
	// orders must use ExecuteOrder or FailCancelOrder. Orders that are
	// terminated by the DEX rather than via a cancel order are considered
	// "revoked", and RevokeOrder should be used to set this status.
	CancelOrder(*order.LimitOrder) error

	// RevokeOrder puts an order into the revoked state, and generates a cancel
	// order to record the action. Orders should be revoked by the DEX according
	// to policy on failed orders. For canceling an order that was matched with
	// a cancel order, use CancelOrder.
	RevokeOrder(order.Order) (cancelID order.OrderID, t time.Time, err error)

	// RevokeOrderUncounted is like RevokeOrder except that the generated cancel
	// order will not be counted against the user. i.e. ExecutedCancelsForUser
	// should not return the cancel orders created this way.
	RevokeOrderUncounted(order.Order) (cancelID order.OrderID, t time.Time, err error)

	// NewArchivedCancel stores a cancel order directly in the executed state. This
	// is used for orders that are canceled when the market is suspended, and therefore
	// do not need to be matched.
	NewArchivedCancel(ord *order.CancelOrder, epochID, epochDur int64) error

	// FailCancelOrder puts an unmatched cancel order into the executed state.
	// For matched cancel orders, use ExecuteOrder.
	FailCancelOrder(*order.CancelOrder) error

	// UpdateOrderFilled updates the filled amount of the given order. This
	// function applies only to limit orders, not cancel or market orders. The
	// filled amount of a market order should be updated by ExecuteOrder.
	UpdateOrderFilled(*order.LimitOrder) error

	// UpdateOrderStatus updates the status and filled amount of the given
	// order.
	UpdateOrderStatus(order.Order, order.OrderStatus) error

	// SetOrderCompleteTime sets the successful completion time for an existing
	// order. This will follow the final step in swap negotiation, for an order
	// that is not on the book.
	SetOrderCompleteTime(ord order.Order, compTimeMs int64) error
}

OrderArchiver is the interface required for storage and retrieval of all order data.

type OrderStatus

type OrderStatus struct {
	ID     order.OrderID
	Status order.OrderStatus
}

OrderStatus is the current status of an order.

type PreimageResult

type PreimageResult struct {
	Miss bool
	Time int64
	ID   order.OrderID
}

PreimageResult is the outcome of preimage collection for an order in an epoch that closed at a certain time.

type SwapArchiver

type SwapArchiver interface {
	// ActiveSwaps loads the full details for all active swaps across all markets.
	ActiveSwaps() ([]*SwapDataFull, error)

	// SwapData retrieves the swap/match status and the current SwapData.
	SwapData(mid MarketMatchID) (order.MatchStatus, *SwapData, error)

	// SaveMatchAckSigA records the match data acknowledgement signature from
	// swap party A (the initiator), which is the maker in the DEX.
	SaveMatchAckSigA(mid MarketMatchID, sig []byte) error

	// SaveMatchAckSigB records the match data acknowledgement signature from
	// swap party B (the participant), which is the taker in the DEX.
	SaveMatchAckSigB(mid MarketMatchID, sig []byte) error

	// SaveContractA records party A's swap contract script and the coinID (e.g.
	// transaction output) containing the contract on chain X. Note that this
	// contract contains the secret hash.
	SaveContractA(mid MarketMatchID, contract []byte, coinID []byte, timestamp int64) error

	// SaveAuditAckSigB records party B's signature acknowledging their audit of
	// A's swap contract.
	SaveAuditAckSigB(mid MarketMatchID, sig []byte) error

	// SaveContractB records party B's swap contract script and the coinID (e.g.
	// transaction output) containing the contract on chain Y.
	SaveContractB(mid MarketMatchID, contract []byte, coinID []byte, timestamp int64) error

	// SaveAuditAckSigA records party A's signature acknowledging their audit of
	// B's swap contract.
	SaveAuditAckSigA(mid MarketMatchID, sig []byte) error

	// SaveRedeemA records party A's redemption coinID (e.g. transaction
	// output), which spends party B's swap contract on chain Y. Note that this
	// transaction will contain the secret, which party B extracts.
	SaveRedeemA(mid MarketMatchID, coinID, secret []byte, timestamp int64) error

	// SaveRedeemAckSigB records party B's signature acknowledging party A's
	// redemption, which spent their swap contract on chain Y and revealed the
	// secret.
	SaveRedeemAckSigB(mid MarketMatchID, sig []byte) error

	// SaveRedeemB records party B's redemption coinID (e.g. transaction
	// output), which spends party A's swap contract on chain X. This should
	// also flag the match as inactive.
	SaveRedeemB(mid MarketMatchID, coinID []byte, timestamp int64) error

	// SetMatchInactive sets the swap as done/inactive. This can be because of a
	// failed or successfully completed swap, but in practice this will be used
	// for failed swaps since SaveRedeemB flags the swap as done/inactive. If
	// the match is being marked as inactive prior to MatchComplete (the match
	// was revoked) but the user is not at fault, the forgive bool may be set to
	// true so the outcome will not count against the user who would have the
	// next action in the swap.
	SetMatchInactive(mid MarketMatchID, forgive bool) error
}

SwapArchiver is the interface required for storage and retrieval of swap counterparty data.

In the swap process, the counterparties are: - Initiator or party A on chain X. This is the maker in the DEX. - Participant or party B on chain Y. This is the taker in the DEX.

For each match, a successful swap will generate the following data that must be stored:

  • 5 client signatures. Both parties sign the data to acknowledge (1) the match ack, and (2) the counterparty's contract script and contract transaction. Plus the taker acks the maker's redemption transaction.
  • 2 swap contracts and the associated transaction outputs (more generally, coinIDs), one on each party's blockchain.
  • 2 redemption transaction outputs (coinIDs).

The methods for saving this data are defined below in the order in which the data is expected from the parties.

type SwapData

type SwapData struct {
	SigMatchAckMaker []byte
	SigMatchAckTaker []byte
	ContractA        []byte // contains the secret hash used by both parties
	ContractACoinID  []byte
	ContractATime    int64
	ContractAAckSig  []byte // B's signature of contract A data
	ContractB        []byte
	ContractBCoinID  []byte
	ContractBTime    int64
	ContractBAckSig  []byte // A's signature of contract B data
	RedeemACoinID    []byte
	RedeemASecret    []byte // the secret revealed in A's redeem, also used in B's redeem
	RedeemATime      int64
	RedeemAAckSig    []byte // B's signature of redeem A data
	RedeemBCoinID    []byte
	RedeemBTime      int64
}

SwapData contains the data generated by the clients during swap negotiation.

type SwapDataFull added in v0.2.0

type SwapDataFull struct {
	Base, Quote uint32
	*MatchData
	*SwapData
}

SwapDataFull combines a MatchData, SwapData, and the Base/Quote asset IDs.

Directories

Path Synopsis
driver
pg

Jump to

Keyboard shortcuts

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