Documentation ¶
Index ¶
- Constants
- Variables
- func AuthChallenge(commitHash [32]byte, nonce [32]byte) [32]byte
- func AuthHash(commitHash, challenge [32]byte) [32]byte
- func CommitAccount(acctPubKey [33]byte, nonce [32]byte) [32]byte
- func GenerateRecoveryKeys(ctx context.Context, wallet lndclient.WalletKitClient) ([]*keychain.KeyDescriptor, error)
- func NumConfsForValue(value, maxAccountValue btcutil.Amount) uint32
- func UseLogger(logger btclog.Logger)
- type Account
- type Auctioneer
- type FeeExpr
- type Manager
- func (m *Manager) BumpAccountFee(ctx context.Context, traderKey *btcec.PublicKey, ...) error
- func (m *Manager) CloseAccount(ctx context.Context, traderKey *btcec.PublicKey, feeExpr FeeExpr, ...) (*wire.MsgTx, error)
- func (m *Manager) DepositAccount(ctx context.Context, traderKey *btcec.PublicKey, depositAmount btcutil.Amount, ...) (*Account, *wire.MsgTx, error)
- func (m *Manager) InitAccount(ctx context.Context, value btcutil.Amount, ...) (*Account, error)
- func (m *Manager) QuoteAccount(ctx context.Context, value btcutil.Amount, confTarget uint32) (chainfee.SatPerKWeight, btcutil.Amount, error)
- func (m *Manager) RecoverAccount(ctx context.Context, account *Account) error
- func (m *Manager) RenewAccount(ctx context.Context, traderKey *btcec.PublicKey, newExpiry uint32, ...) (*Account, *wire.MsgTx, error)
- func (m *Manager) Start() error
- func (m *Manager) Stop()
- func (m *Manager) WatchMatchedAccounts(ctx context.Context, matchedAccounts []*btcec.PublicKey) error
- func (m *Manager) WithdrawAccount(ctx context.Context, traderKey *btcec.PublicKey, outputs []*wire.TxOut, ...) (*Account, *wire.MsgTx, error)
- type ManagerConfig
- type Modifier
- func ExpiryModifier(expiry uint32) Modifier
- func HeightHintModifier(heightHint uint32) Modifier
- func IncrementBatchKey() Modifier
- func LatestTxModifier(tx *wire.MsgTx) Modifier
- func OutPointModifier(op wire.OutPoint) Modifier
- func StateModifier(state State) Modifier
- func ValueModifier(value btcutil.Amount) Modifier
- type OutputWithFee
- type OutputsWithImplicitFee
- type Reservation
- type State
- type Store
- type TxFeeEstimator
- type TxSource
Constants ¶
const ( // DefaultFundingConfTarget is the default value used for the account // funding/init target number of blocks to confirmation. We choose a // very high value of one week to arrive at essentially 1 sat/vByte // which used to be the previous default when creating the transaction. DefaultFundingConfTarget uint32 = 144 * 7 )
const ( // MinAccountValue is the minimum value for an account output in // satoshis. MinAccountValue btcutil.Amount = 100000 )
const Subsystem = "ACCT"
Variables ¶
var ( // DefaultAccountKeyWindow is the number of account keys that are // derived to be checked on recovery. This is the absolute maximum // number of accounts that can ever be restored. But the trader doesn't // necessarily make as many requests on recovery, if no accounts are // found for a certain number of tries. DefaultAccountKeyWindow uint32 = 500 )
var ( // ErrNoPendingBatch is an error returned when we attempt to retrieve // the ID of a pending batch, but one does not exist. ErrNoPendingBatch = errors.New("no pending batch found") )
Functions ¶
func AuthChallenge ¶
AuthChallenge creates the authentication challenge that is sent from the server as step 2 of the 3-way authentication handshake with the client. It returns the authentication challenge which is SHA256(commit_hash || nonce).
func AuthHash ¶
AuthHash creates the authentication hash that is signed as part of step 3 of the 3-way authentication handshake. It returns the authentication hash which is SHA256(commit_hash || auth_challenge) which is equal to SHA256(SHA256(accountPubKey || nonce1) || SHA256(commit_hash || nonce2)).
func CommitAccount ¶
CommitAccount creates the commitment hash that is used for the first part of the 3-way authentication handshake with the server. It returns the commitment hash which is SHA256(accountPubKey || nonce).
func GenerateRecoveryKeys ¶
func GenerateRecoveryKeys(ctx context.Context, wallet lndclient.WalletKitClient) ([]*keychain.KeyDescriptor, error)
GenerateRecoveryKeys generates a list of key descriptors for all possible keys that could be used for trader accounts, up to a hard coded limit.
func NumConfsForValue ¶
numConfsForValue chooses an appropriate number of confirmations to wait for an account based on its initial value.
TODO(wilmer): Determine the recommend number of blocks to wait for a particular output size given the current block reward and a user's "risk threshold" (basically a multiplier for the amount of work/fiat-burnt that would need to be done to undo N blocks).
Types ¶
type Account ¶
type Account struct { // Value is the value of the account reflected in on-chain output that // backs the existence of an account. Value btcutil.Amount // Expiry is the expiration block height of an account. After this // point, the trader is able to withdraw the funds from their account // without cooperation of the auctioneer. Expiry uint32 // TraderKey is the base trader's key in the 2-of-2 multi-sig // construction of a CLM account. This key will never be included in the // account script, but rather it will be tweaked with the per-batch key // and the account secret to prevent script reuse and provide plausible // deniability between account outputs to third parties. TraderKey *keychain.KeyDescriptor // AuctioneerKey is the base auctioneer's key in the 2-of-2 multi-sig // construction of a CLM account. This key will never be included in the // account script, but rather it will be tweaked with the per-batch // trader key to prevent script reuse and provide plausible deniability // between account outputs to third parties. AuctioneerKey *btcec.PublicKey // BatchKey is the batch key that is used to tweak the trader key of an // account with, along with the secret. This will be incremented by the // curve's base point each time the account is modified or participates // in a cleared batch to prevent output script reuse for accounts // on-chain. BatchKey *btcec.PublicKey // Secret is a static shared secret between the trader and the // auctioneer that is used to tweak the trader key of an account with, // along with the batch key. This ensures that only the trader and // auctioneer are able to successfully identify every past/future output // of an account. Secret [32]byte // State describes the state of the account. State State // HeightHint is the earliest height in the chain at which we can find // the account output in a block. HeightHint uint32 // OutPoint is the outpoint of the output used to fund the account. This // only exists once the account has reached StatePendingOpen. OutPoint wire.OutPoint // LatestTx is the latest transaction of an account. // // NOTE: This is only nil within the StateInitiated phase. There are no // guarantees as to whether the transaction has its witness populated. LatestTx *wire.MsgTx }
Account encapsulates all of the details of a CLM account on-chain from the trader's perspective.
func (*Account) NextOutputScript ¶
NextOutputScript returns the next on-chain output script that is to be associated with the account. This is done by using the next batch key, which results from incrementing the current one by its curve's base point.
type Auctioneer ¶
type Auctioneer interface { // ReserveAccount reserves an account of the specified value with the // auctioneer. The auctioneer checks the account value against current // min/max values configured. If the value is valid, it returns the // public key we should use for them in our 2-of-2 multi-sig // construction. To address an edge case in the account recovery where // the trader crashes before confirming the account with the auctioneer, // we also send the trader key and expiry along with the reservation. ReserveAccount(context.Context, btcutil.Amount, uint32, *btcec.PublicKey) (*Reservation, error) // InitAccount initializes an account with the auctioneer such that it // can be used once fully confirmed. InitAccount(context.Context, *Account) error // ModifyAccount sends an intent to the auctioneer that we'd like to // modify the account with the associated trader key. The auctioneer's // signature is returned, allowing us to broadcast a transaction // spending from the account allowing our modifications to take place. // The inputs and outputs provided should exclude the account input // being spent and the account output potentially being recreated, since // the auctioneer can construct those themselves. ModifyAccount(context.Context, *Account, []*wire.TxIn, []*wire.TxOut, []Modifier) ([]byte, error) // StartAccountSubscription opens a stream to the server and subscribes // to all updates that concern the given account, including all orders // that spend from that account. Only a single stream is ever open to // the server, so a second call to this method will send a second // subscription over the same stream, multiplexing all messages into the // same connection. A stream can be long-lived, so this can be called // for every account as soon as it's confirmed open. This method will // return as soon as the authentication was successful. Messages sent // from the server can then be received on the FromServerChan channel. StartAccountSubscription(context.Context, *keychain.KeyDescriptor) error // Terms returns the current dynamic auctioneer terms like max account // size, max order duration in blocks and the auction fee schedule. Terms(ctx context.Context) (*terms.AuctioneerTerms, error) }
Auctioneer provides us with the different ways we are able to communicate with our auctioneer during the process of opening/closing/modifying accounts.
type FeeExpr ¶
type FeeExpr interface { // CloseOutputs is the list of outputs that should be used for the // closing transaction of an account based on the concrete fee // expression implementation. CloseOutputs(btcutil.Amount, witnessType) ([]*wire.TxOut, error) }
FeeExpr represents the different ways a transaction fee can be expressed in terms of a transaction's resulting outputs.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is responsible for the management of accounts on-chain.
func NewManager ¶
func NewManager(cfg *ManagerConfig) *Manager
NewManager instantiates a new Manager backed by the given config.
func (*Manager) BumpAccountFee ¶
func (m *Manager) BumpAccountFee(ctx context.Context, traderKey *btcec.PublicKey, newFeeRate chainfee.SatPerKWeight) error
BumpAccountFee attempts to bump the fee of an account's most recent transaction. This is done by locating an eligible output for lnd to CPFP, otherwise the fee bump will not succeed. Further invocations of this call for the same account will result in the child being replaced by the higher fee transaction (RBF).
func (*Manager) CloseAccount ¶
func (m *Manager) CloseAccount(ctx context.Context, traderKey *btcec.PublicKey, feeExpr FeeExpr, bestHeight uint32) (*wire.MsgTx, error)
CloseAccount attempts to close the account associated with the given trader key. Closing the account requires a signature of the auctioneer if the account has not yet expired. The account funds are swept according to the provided fee expression.
func (*Manager) DepositAccount ¶
func (m *Manager) DepositAccount(ctx context.Context, traderKey *btcec.PublicKey, depositAmount btcutil.Amount, feeRate chainfee.SatPerKWeight, bestHeight uint32) (*Account, *wire.MsgTx, error)
DepositAccount attempts to deposit funds into the account associated with the given trader key such that the new account value is met using inputs sourced from the backing lnd node's wallet. If needed, a change output that does back to lnd may be added to the deposit transaction.
func (*Manager) InitAccount ¶
func (m *Manager) InitAccount(ctx context.Context, value btcutil.Amount, expiry, bestHeight, confTarget uint32) (*Account, error)
InitAccount handles a request to create a new account with the provided parameters.
func (*Manager) QuoteAccount ¶
func (m *Manager) QuoteAccount(ctx context.Context, value btcutil.Amount, confTarget uint32) (chainfee.SatPerKWeight, btcutil.Amount, error)
QuoteAccount returns the expected fee rate and total miner fee to send to an account funding output with the given confTarget.
func (*Manager) RecoverAccount ¶
RecoverAccount re-introduces a recovered account into the database and starts all watchers necessary depending on the account's state.
func (*Manager) RenewAccount ¶
func (m *Manager) RenewAccount(ctx context.Context, traderKey *btcec.PublicKey, newExpiry uint32, feeRate chainfee.SatPerKWeight, bestHeight uint32) (*Account, *wire.MsgTx, error)
RenewAccount updates the expiration of an open/expired account. This will always require a signature from the auctioneer, even after the account has expired, to ensure the auctioneer is aware the account is being renewed.
func (*Manager) Stop ¶
func (m *Manager) Stop()
Stop safely stops any ongoing operations within the Manager.
func (*Manager) WatchMatchedAccounts ¶
func (m *Manager) WatchMatchedAccounts(ctx context.Context, matchedAccounts []*btcec.PublicKey) error
WatchMatchedAccounts resumes accounts that were just matched in a batch and are expecting the batch transaction to confirm as their next account output. This will cancel all previous spend and conf watchers of all accounts involved in the batch.
func (*Manager) WithdrawAccount ¶
func (m *Manager) WithdrawAccount(ctx context.Context, traderKey *btcec.PublicKey, outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight, bestHeight uint32) (*Account, *wire.MsgTx, error)
WithdrawAccount attempts to withdraw funds from the account associated with the given trader key into the provided outputs.
type ManagerConfig ¶
type ManagerConfig struct { // Store is responsible for storing and retrieving account information // reliably. Store Store // Auctioneer provides us with the different ways we are able to // communicate with our auctioneer during the process of // opening/closing/modifying accounts. Auctioneer Auctioneer // Wallet handles all of our on-chain transaction interaction, whether // that is deriving keys, creating transactions, etc. Wallet lndclient.WalletKitClient // Signer is responsible for deriving shared secrets for accounts // between the trader and auctioneer and signing account-related // transactions. Signer lndclient.SignerClient // ChainNotifier is responsible for requesting confirmation and spend // notifications for accounts. ChainNotifier lndclient.ChainNotifierClient // TxSource is a source that provides us with transactions previously // broadcast by us. TxSource TxSource // TxFeeEstimator is an estimator that can calculate the total on-chain // fees to send to an account output. TxFeeEstimator TxFeeEstimator // TxLabelPrefix is set, then all transactions the account manager // makes will use this string as a prefix for added transaction labels. TxLabelPrefix string }
ManagerConfig contains all of the required dependencies for the Manager to carry out its duties.
type Modifier ¶
type Modifier func(*Account)
Modifier abstracts the modification of an account through a function.
func ExpiryModifier ¶
ExpiryModifier is a functional option that modifies the expiry of an account.
func HeightHintModifier ¶
HeightHintModifier is a functional option that modifies the height hint of an account.
func IncrementBatchKey ¶
func IncrementBatchKey() Modifier
IncrementBatchKey is a functional option that increments the batch key of an account by adding the curve's base point.
func LatestTxModifier ¶
LatestTxModifier is a functional option that modifies the latest transaction of an account.
func OutPointModifier ¶
OutPointModifier is a functional option that modifies the outpoint of an account.
func StateModifier ¶
StateModifier is a functional option that modifies the state of an account.
func ValueModifier ¶
ValueModifier is a functional option that modifies the value of an account.
type OutputWithFee ¶
type OutputWithFee struct { // PkScript is the destination output script. Note that this may be nil, // in which case a wallet-derived P2WKH script should be used. PkScript []byte // FeeRate is the accompanying fee rate to use to determine the // transaction fee. FeeRate chainfee.SatPerKWeight }
OutputWithFee signals that a single transaction output along with a fee rate is used to determine the transaction fee.
func (*OutputWithFee) CloseOutputs ¶
type OutputsWithImplicitFee ¶
OutputsWithImplicitFee signals that the transaction fee is implicitly defined by the output values provided, i.e., the fee is determined by subtracting the total output value from the total input value.
func (OutputsWithImplicitFee) CloseOutputs ¶
func (o OutputsWithImplicitFee) CloseOutputs(accountValue btcutil.Amount, witnessType witnessType) ([]*wire.TxOut, error)
Outputs is the list of outputs that should be used for the closing transaction of an account using an implicit fee expression.
func (OutputsWithImplicitFee) Outputs ¶
func (o OutputsWithImplicitFee) Outputs() []*wire.TxOut
Outputs returns the set of outputs.
type Reservation ¶
type Reservation struct { // AuctioneerKey is the base auctioneer's key in the 2-of-2 multi-sig // construction of a CLM account. This key will never be included in the // account script, but rather it will be tweaked with the per-batch // trader key to prevent script reuse and provide plausible deniability // between account outputs to third parties. AuctioneerKey *btcec.PublicKey // InitialBatchKey is the initial batch key that is used to tweak the // trader key of an account. InitialBatchKey *btcec.PublicKey }
Reservation contains information about the different keys required for to create a new account.
type State ¶
type State uint8
State describes the different possible states of an account.
const ( // StateInitiated denotes the initial state of an account. When an // account is in this state, then it should be funded with a // transaction. StateInitiated State = 0 // StatePendingOpen denotes that we've broadcast the account's funding // transaction and are currently waiting for its confirmation. StatePendingOpen State = 1 // StatePendingUpdate denotes that the account has undergone an update // on-chain as part of a trader modification and we are currently // waiting for its confirmation. StatePendingUpdate State = 2 // StateOpen denotes that the account's funding transaction has been // included in the chain with sufficient depth. StateOpen State = 3 // StateExpired denotes that the chain has reached an account's // expiration height. An account in this state can still be used if // renewed. StateExpired State = 4 // StatePendingClosed denotes that an account was fully spent by a // transaction broadcast by the trader and is pending its confirmation. StatePendingClosed State = 5 // StateClosed denotes that an account was closed by a transaction // broadcast by the trader that fully spent the account. An account in // this state can no longer be used. StateClosed State = 6 // StateCanceledAfterRecovery denotes that the account was attempted to // be recovered but failed because the opening transaction wasn't found // by lnd. This could be because it was never published or it never // confirmed. Then the funds are SAFU and the account can be considered // to never have been opened in the first place. StateCanceledAfterRecovery State = 7 // StatePendingBatch denotes an account that recently participated in a // batch and is not yet confirmed. StatePendingBatch State = 8 // StateExpiredPendingUpdate denotes that the chain has reached an // account's expiration height while the account had a pending update // that has yet to confirm. This state exists to ensure an account can // only be renewed once confirmed and expired. StateExpiredPendingUpdate State = 9 )
NOTE: We avoid the use of iota as these can be persisted to disk.
type Store ¶
type Store interface { // AddAccount adds a record for the account to the database. AddAccount(*Account) error // UpdateAccount updates an account in the database according to the // given modifiers. UpdateAccount(*Account, ...Modifier) error // Account retrieves the account associated with the given trader key // from the database. Account(*btcec.PublicKey) (*Account, error) // Accounts retrieves all existing accounts. Accounts() ([]*Account, error) // PendingBatch determines whether we currently have a pending batch. // If a batch doesn't exist, ErrNoPendingBatch is returned. PendingBatch() error // MarkBatchComplete marks the batch with the given ID as complete, // indicating that the staged account updates can be applied to disk. MarkBatchComplete() error // LockID retrieves the global lock ID we'll use to lock any outputs // when performing coin selection. LockID() (wtxmgr.LockID, error) }
Store is responsible for storing and retrieving account information reliably.
type TxFeeEstimator ¶
type TxFeeEstimator interface { // EstimateFeeToP2WSH estimates the total chain fees in satoshis to send // the given amount to a single P2WSH output with the given target // confirmation. EstimateFeeToP2WSH(ctx context.Context, amt btcutil.Amount, confTarget int32) (btcutil.Amount, error) }
TxFeeEstimator is a type that provides us with a realistic fee estimation to send coins in a transaction.
type TxSource ¶
type TxSource interface { // ListTransactions returns all known transactions of the backing lnd // node. It takes a start and end block height which can be used to // limit the block range that we query over. These values can be left // as zero to include all blocks. To include unconfirmed transactions // in the query, endHeight must be set to -1. ListTransactions(ctx context.Context, startHeight, endHeight int32) ([]lndclient.Transaction, error) }
TxSource is a source that provides us with transactions previously broadcast by us.