diff --git a/auctioneer/client.go b/auctioneer/client.go index f6d60b6..cbac82e 100644 --- a/auctioneer/client.go +++ b/auctioneer/client.go @@ -18,6 +18,7 @@ import ( "github.com/lightninglabs/llm/account" "github.com/lightninglabs/llm/clmrpc" "github.com/lightninglabs/llm/order" + "github.com/lightninglabs/llm/terms" "github.com/lightninglabs/lndclient" "github.com/lightningnetwork/lnd/keychain" "google.golang.org/grpc" @@ -1090,13 +1091,13 @@ func unmarshallServerAccount(keyDesc *keychain.KeyDescriptor, } // FeeQuote returns the current fee schedule for the auction. -func (c *Client) FeeQuote(ctx context.Context) (*order.LinearFeeSchedule, error) { +func (c *Client) FeeQuote(ctx context.Context) (*terms.LinearFeeSchedule, error) { resp, err := c.client.FeeQuote(ctx, &clmrpc.FeeQuoteRequest{}) if err != nil { return nil, err } - return order.NewLinearFeeSchedule( + return terms.NewLinearFeeSchedule( btcutil.Amount(resp.ExecutionFee.BaseFee), btcutil.Amount(resp.ExecutionFee.FeeRate), ), nil diff --git a/cmd/llm/order.go b/cmd/llm/order.go index 92bc552..2ec83e7 100644 --- a/cmd/llm/order.go +++ b/cmd/llm/order.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightninglabs/llm/clmrpc" "github.com/lightninglabs/llm/order" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/urfave/cli" ) @@ -263,7 +264,7 @@ func printOrderDetails(client clmrpc.TraderClient, amt btcutil.Amount, return err } - feeSchedule := order.NewLinearFeeSchedule( + feeSchedule := terms.NewLinearFeeSchedule( btcutil.Amount(auctionFee.ExecutionFee.BaseFee), btcutil.Amount(auctionFee.ExecutionFee.FeeRate), ) diff --git a/order/batch.go b/order/batch.go index 166ad1e..c96184d 100644 --- a/order/batch.go +++ b/order/batch.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightninglabs/llm/account" "github.com/lightninglabs/llm/clmrpc" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -157,7 +158,7 @@ type Batch struct { // ExecutionFee is the FeeSchedule that was used by the server to // calculate the execution fee. - ExecutionFee FeeSchedule + ExecutionFee terms.FeeSchedule // ClearingPrice is the fixed rate the orders were cleared at. ClearingPrice FixedRatePremium diff --git a/order/batch_verifier.go b/order/batch_verifier.go index eecddde..e13c81c 100644 --- a/order/batch_verifier.go +++ b/order/batch_verifier.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/llm/account" + "github.com/lightninglabs/llm/terms" "github.com/lightninglabs/lndclient" "github.com/lightningnetwork/lnd/input" ) @@ -213,7 +214,7 @@ func (v *batchVerifier) Verify(batch *Batch) error { // validateMatchedOrder validates our order against another trader's order and // tallies up our order's account balance. func (v *batchVerifier) validateMatchedOrder(tally *AccountTally, - ourOrder Order, otherOrder *MatchedOrder, executionFee FeeSchedule, + ourOrder Order, otherOrder *MatchedOrder, executionFee terms.FeeSchedule, clearingPrice FixedRatePremium) error { // Order type must be opposite. diff --git a/order/batch_verifier_test.go b/order/batch_verifier_test.go index d4e0e11..72200fa 100644 --- a/order/batch_verifier_test.go +++ b/order/batch_verifier_test.go @@ -11,6 +11,7 @@ import ( "github.com/lightninglabs/llm/account" "github.com/lightninglabs/llm/clmrpc" "github.com/lightninglabs/llm/internal/test" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -198,7 +199,7 @@ func TestBatchVerifier(t *testing.T) { doVerify: func(v BatchVerifier, a *Ask, b1, b2 *Bid, b *Batch) error { - b.ExecutionFee = NewLinearFeeSchedule(1, 1) + b.ExecutionFee = terms.NewLinearFeeSchedule(1, 1) return v.Verify(b) }, }, @@ -208,7 +209,7 @@ func TestBatchVerifier(t *testing.T) { doVerify: func(v BatchVerifier, a *Ask, b1, b2 *Bid, b *Batch) error { - b.ExecutionFee = NewLinearFeeSchedule(0, 0) + b.ExecutionFee = terms.NewLinearFeeSchedule(0, 0) b.BatchTX.TxOut[2].Value += 2220 b.AccountDiffs[0].EndingBalance += 2220 b.AccountDiffs[1].EndingBalance += 2220 @@ -221,7 +222,7 @@ func TestBatchVerifier(t *testing.T) { doVerify: func(v BatchVerifier, a *Ask, b1, b2 *Bid, b *Batch) error { - b.ExecutionFee = NewLinearFeeSchedule(0, 0) + b.ExecutionFee = terms.NewLinearFeeSchedule(0, 0) b.BatchTX.TxOut[2].Value += 2220 b.AccountDiffs[0].EndingBalance += 2220 b.AccountDiffs[1].EndingBalance += 2220 @@ -401,7 +402,7 @@ func TestBatchVerifier(t *testing.T) { Version: DefaultVersion, MatchedOrders: matchedOrders, AccountDiffs: accountDiffs, - ExecutionFee: NewLinearFeeSchedule( + ExecutionFee: terms.NewLinearFeeSchedule( execFeeBase, execFeeRate, ), ClearingPrice: clearingPrice, diff --git a/order/interface.go b/order/interface.go index af71fe6..346c79b 100644 --- a/order/interface.go +++ b/order/interface.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightninglabs/llm/account" "github.com/lightninglabs/llm/clmrpc" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -168,7 +169,7 @@ type Order interface { // ReservedValue returns the maximum value that could be deducted from // the account if the order is is matched, and therefore has to be // reserved to ensure the trader can afford it. - ReservedValue(feeSchedule FeeSchedule) btcutil.Amount + ReservedValue(feeSchedule terms.FeeSchedule) btcutil.Amount } // Kit stores all the common fields that are used to express the decision to @@ -347,7 +348,7 @@ func reservedValue(o Order, // ReservedValue returns the maximum value that could be deducted from a single // account if the ask is is matched under the worst case fee conditions. -func (a *Ask) ReservedValue(feeSchedule FeeSchedule) btcutil.Amount { +func (a *Ask) ReservedValue(feeSchedule terms.FeeSchedule) btcutil.Amount { // For an ask the clearing price will be no lower than the ask's fixed // rate, resulting in the smallest gain for the asker. clearingPrice := FixedRatePremium(a.FixedRate) @@ -410,7 +411,7 @@ func (b *Bid) Digest() ([sha256.Size]byte, error) { // ReservedValue returns the maximum value that could be deducted from a single // account if the bid is is matched under the worst case fee conditions. -func (b *Bid) ReservedValue(feeSchedule FeeSchedule) btcutil.Amount { +func (b *Bid) ReservedValue(feeSchedule terms.FeeSchedule) btcutil.Amount { // For a bid, the final clearing price is never higher // that the bid's fixed rate, resulting in the highest possible // premium paid bu the bidder. diff --git a/order/interface_test.go b/order/interface_test.go index db01c54..deda7fd 100644 --- a/order/interface_test.go +++ b/order/interface_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/btcsuite/btcutil" + "github.com/lightninglabs/llm/terms" ) // TestOrderReservedValue checks orders' ReservedValue merhod returning the @@ -11,7 +12,7 @@ import ( func TestOrderReservedValue(t *testing.T) { t.Parallel() - simpleFeeSchedule := NewLinearFeeSchedule(1, 100) + simpleFeeSchedule := terms.NewLinearFeeSchedule(1, 100) testCases := []struct { name string diff --git a/order/manager.go b/order/manager.go index 8b9cf5c..708af3f 100644 --- a/order/manager.go +++ b/order/manager.go @@ -10,6 +10,7 @@ import ( "time" "github.com/lightninglabs/llm/account" + "github.com/lightninglabs/llm/terms" "github.com/lightninglabs/lndclient" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -122,7 +123,7 @@ func (m *Manager) Stop() { // PrepareOrder validates an order, signs it and then stores it locally. func (m *Manager) PrepareOrder(ctx context.Context, order Order, - acct *account.Account, feeSchedule FeeSchedule) ( + acct *account.Account, feeSchedule terms.FeeSchedule) ( *ServerOrderParams, error) { // Verify incoming request for formal validity. @@ -195,7 +196,7 @@ func (m *Manager) PrepareOrder(ctx context.Context, order Order, // validateOrder makes sure an order is formally correct and that the associated // account contains enough balance to execute the order. func (m *Manager) validateOrder(order Order, acct *account.Account, - feeSchedule FeeSchedule) error { + feeSchedule terms.FeeSchedule) error { // First parse order type specific fields. switch o := order.(type) { diff --git a/order/manager_test.go b/order/manager_test.go index ae2f1ea..d7438fd 100644 --- a/order/manager_test.go +++ b/order/manager_test.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightninglabs/llm/account" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/keychain" ) @@ -49,7 +50,7 @@ func TestValidateOrderAccountIsolation(t *testing.T) { MaxDuration: 144, } - simpleFeeSchedule := NewLinearFeeSchedule(1, 100) + simpleFeeSchedule := terms.NewLinearFeeSchedule(1, 100) // Submitting this order for account B should pass validation. err := orderManager.validateOrder( diff --git a/order/rpc_parse.go b/order/rpc_parse.go index 8bfa847..488d883 100644 --- a/order/rpc_parse.go +++ b/order/rpc_parse.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightninglabs/llm/clmrpc" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -218,7 +219,7 @@ func ParseRPCBatch(prepareMsg *clmrpc.OrderMatchPrepare) (*Batch, if prepareMsg.ExecutionFee == nil { return nil, fmt.Errorf("execution fee missing") } - b.ExecutionFee = NewLinearFeeSchedule( + b.ExecutionFee = terms.NewLinearFeeSchedule( btcutil.Amount(prepareMsg.ExecutionFee.BaseFee), btcutil.Amount(prepareMsg.ExecutionFee.FeeRate), ) diff --git a/order/tradingfees.go b/order/tradingfees.go index 962c049..0444c93 100644 --- a/order/tradingfees.go +++ b/order/tradingfees.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwallet/wallet/txrules" "github.com/lightninglabs/llm/clmscript" + "github.com/lightninglabs/llm/terms" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -54,60 +55,6 @@ func (f FixedRatePremium) LumpSumPremium(amt btcutil.Amount, return btcutil.Amount(premiumPerBlock * float64(durationBlocks)) } -// FeeSchedule is an interface that represents the configuration source that -// the auctioneer will use to determine how much to charge in fees for each -// trader. -type FeeSchedule interface { - // BaseFee is the base fee the auctioneer will charge the traders for - // each executed order. - BaseFee() btcutil.Amount - - // ExecutionFee computes the execution fee (usually based off of a - // rate) for the target amount. - ExecutionFee(amt btcutil.Amount) btcutil.Amount -} - -// LinearFeeSchedule is a FeeSchedule that calculates the execution fee based -// upon a static base fee and a variable fee rate in parts per million. -type LinearFeeSchedule struct { - baseFee btcutil.Amount - feeRate btcutil.Amount -} - -// BaseFee is the base fee the auctioneer will charge the traders for each -// executed order. -// -// NOTE: This method is part of the orderT.FeeSchedule interface. -func (s *LinearFeeSchedule) BaseFee() btcutil.Amount { - return s.baseFee -} - -// FeeRate is the variable fee rate in parts per million. -func (s *LinearFeeSchedule) FeeRate() btcutil.Amount { - return s.feeRate -} - -// ExecutionFee computes the execution fee (usually based off of a rate) for -// the target amount. -// -// NOTE: This method is part of the orderT.FeeSchedule interface. -func (s *LinearFeeSchedule) ExecutionFee(amt btcutil.Amount) btcutil.Amount { - return amt * s.feeRate / 1_000_000 -} - -// NewLinearFeeSchedule creates a new linear fee schedule based upon a static -// base fee and a relative fee rate in parts per million. -func NewLinearFeeSchedule(baseFee, feeRate btcutil.Amount) *LinearFeeSchedule { - return &LinearFeeSchedule{ - baseFee: baseFee, - feeRate: feeRate, - } -} - -// This is a compile time check to make certain that LinearFeeSchedule -// implements the orderT.FeeSchedule interface. -var _ FeeSchedule = (*LinearFeeSchedule)(nil) - // PerBlockPremium calculates the absolute premium in fractions of satoshis for // a one block duration from the amount and the specified fee rate in parts per // million. @@ -175,7 +122,7 @@ type AccountTally struct { // makerDelta calculates an account's balance and fee difference for a single // order where the account is involved on the maker side. It returns the // balance delta, fees accrued, and execution fee paid. -func makerDelta(feeSchedule FeeSchedule, price FixedRatePremium, +func makerDelta(feeSchedule terms.FeeSchedule, price FixedRatePremium, totalSats btcutil.Amount, duration uint32) (btcutil.Amount, btcutil.Amount, btcutil.Amount) { @@ -201,7 +148,7 @@ func makerDelta(feeSchedule FeeSchedule, price FixedRatePremium, // CalcMakerDelta calculates an account's balance and fee difference for a // single order where the account is involved on the maker side. It returns the // execution fee that is collected by the auctioneer. -func (t *AccountTally) CalcMakerDelta(feeSchedule FeeSchedule, +func (t *AccountTally) CalcMakerDelta(feeSchedule terms.FeeSchedule, price FixedRatePremium, totalSats btcutil.Amount, duration uint32) btcutil.Amount { @@ -220,7 +167,7 @@ func (t *AccountTally) CalcMakerDelta(feeSchedule FeeSchedule, // takerDelta calculates an account's balance and fee difference for a single // order where the account is involved on the taker side. It returns the // balance delta, taker fees paid, and execution fee paid. -func takerDelta(feeSchedule FeeSchedule, +func takerDelta(feeSchedule terms.FeeSchedule, price FixedRatePremium, totalSats btcutil.Amount, duration uint32) (btcutil.Amount, btcutil.Amount, btcutil.Amount) { @@ -242,7 +189,7 @@ func takerDelta(feeSchedule FeeSchedule, // CalcTakerDelta calculates an account's balance and fee difference for a // single order where the account is involved on the taker side. It returns the // execution fee that is collected by the auctioneer. -func (t *AccountTally) CalcTakerDelta(feeSchedule FeeSchedule, +func (t *AccountTally) CalcTakerDelta(feeSchedule terms.FeeSchedule, price FixedRatePremium, totalSats btcutil.Amount, duration uint32) btcutil.Amount { @@ -286,6 +233,8 @@ func minNoDustAccountSize() btcutil.Amount { // executionFee calculates the execution fee which is the base fee plus the // execution fee which scales based on the order size. -func executionFee(amount btcutil.Amount, schedule FeeSchedule) btcutil.Amount { +func executionFee(amount btcutil.Amount, + schedule terms.FeeSchedule) btcutil.Amount { + return schedule.BaseFee() + schedule.ExecutionFee(amount) } diff --git a/terms/fees.go b/terms/fees.go new file mode 100644 index 0000000..16bc939 --- /dev/null +++ b/terms/fees.go @@ -0,0 +1,57 @@ +package terms + +import "github.com/btcsuite/btcutil" + +// FeeSchedule is an interface that represents the configuration source that +// the auctioneer will use to determine how much to charge in fees for each +// trader. +type FeeSchedule interface { + // BaseFee is the base fee the auctioneer will charge the traders for + // each executed order. + BaseFee() btcutil.Amount + + // ExecutionFee computes the execution fee (usually based off of a + // rate) for the target amount. + ExecutionFee(amt btcutil.Amount) btcutil.Amount +} + +// LinearFeeSchedule is a FeeSchedule that calculates the execution fee based +// upon a static base fee and a variable fee rate in parts per million. +type LinearFeeSchedule struct { + baseFee btcutil.Amount + feeRate btcutil.Amount +} + +// BaseFee is the base fee the auctioneer will charge the traders for each +// executed order. +// +// NOTE: This method is part of the orderT.FeeSchedule interface. +func (s *LinearFeeSchedule) BaseFee() btcutil.Amount { + return s.baseFee +} + +// FeeRate is the variable fee rate in parts per million. +func (s *LinearFeeSchedule) FeeRate() btcutil.Amount { + return s.feeRate +} + +// ExecutionFee computes the execution fee (usually based off of a rate) for +// the target amount. +// +// NOTE: This method is part of the orderT.FeeSchedule interface. +func (s *LinearFeeSchedule) ExecutionFee(amt btcutil.Amount) btcutil.Amount { + return amt * s.feeRate / 1_000_000 +} + +// NewLinearFeeSchedule creates a new linear fee schedule based upon a static +// base fee and a relative fee rate in parts per million. +func NewLinearFeeSchedule(baseFee, feeRate btcutil.Amount) *LinearFeeSchedule { + return &LinearFeeSchedule{ + baseFee: baseFee, + feeRate: feeRate, + } +} + +// This is a compile time check to make certain that LinearFeeSchedule +// implements the orderT.FeeSchedule interface. +var _ FeeSchedule = (*LinearFeeSchedule)(nil)