multi: move FeeSchedule to terms package

As a preparation to avoid package import cycles when introducing more
generic terms, we move the FeeSchedule interface and its
LinearFeeSchedule implementation to the terms package.
This commit is contained in:
Oliver Gugger 2020-08-18 13:15:34 +02:00
parent 61dec56810
commit 3df4e2f005
No known key found for this signature in database
GPG key ID: 8E4256593F177720
12 changed files with 92 additions and 76 deletions

View file

@ -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

View file

@ -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),
)

View file

@ -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

View file

@ -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.

View file

@ -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,

View file

@ -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.

View file

@ -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

View file

@ -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) {

View file

@ -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(

View file

@ -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),
)

View file

@ -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)
}

57
terms/fees.go Normal file
View file

@ -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)