mirror of
https://github.com/lightninglabs/pool.git
synced 2026-08-14 12:43:03 +02:00
order+rpcserver: enforce order duration limit and multiple
This commit is contained in:
parent
36f50534dd
commit
7fb4ef9782
3 changed files with 45 additions and 25 deletions
|
|
@ -123,11 +123,11 @@ 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 terms.FeeSchedule) (
|
||||
*ServerOrderParams, error) {
|
||||
acct *account.Account,
|
||||
terms *terms.AuctioneerTerms) (*ServerOrderParams, error) {
|
||||
|
||||
// Verify incoming request for formal validity.
|
||||
err := m.validateOrder(order, acct, feeSchedule)
|
||||
err := m.validateOrder(order, acct, terms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -196,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 terms.FeeSchedule) error {
|
||||
terms *terms.AuctioneerTerms) error {
|
||||
|
||||
// First parse order type specific fields.
|
||||
switch o := order.(type) {
|
||||
|
|
@ -205,12 +205,30 @@ func (m *Manager) validateOrder(order Order, acct *account.Account,
|
|||
return fmt.Errorf("invalid max duration, must be "+
|
||||
"at least %d", MinimumOrderDurationBlocks)
|
||||
}
|
||||
if o.MaxDuration > terms.MaxOrderDuration {
|
||||
return fmt.Errorf("invalid max duration, must be "+
|
||||
"smaller than or equal to %d",
|
||||
terms.MaxOrderDuration)
|
||||
}
|
||||
if o.MaxDuration%MinimumOrderDurationBlocks != 0 {
|
||||
return fmt.Errorf("invalid max duration, must be "+
|
||||
"multiple of %d", MinimumOrderDurationBlocks)
|
||||
}
|
||||
|
||||
case *Bid:
|
||||
if o.MinDuration < MinimumOrderDurationBlocks {
|
||||
return fmt.Errorf("invalid min duration, must be "+
|
||||
"at least %d", MinimumOrderDurationBlocks)
|
||||
}
|
||||
if o.MinDuration > terms.MaxOrderDuration {
|
||||
return fmt.Errorf("invalid min duration, must be "+
|
||||
"smaller than or equal to %d",
|
||||
terms.MaxOrderDuration)
|
||||
}
|
||||
if o.MinDuration%MinimumOrderDurationBlocks != 0 {
|
||||
return fmt.Errorf("invalid min duration, must be "+
|
||||
"multiple of %d", MinimumOrderDurationBlocks)
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid order type: %v", o)
|
||||
|
|
@ -232,6 +250,7 @@ func (m *Manager) validateOrder(order Order, acct *account.Account,
|
|||
// value when adding this order.
|
||||
var acctKey [33]byte
|
||||
copy(acctKey[:], acct.TraderKey.PubKey.SerializeCompressed())
|
||||
feeSchedule := terms.FeeSchedule()
|
||||
reserved := order.ReservedValue(feeSchedule)
|
||||
for _, o := range dbOrders {
|
||||
// Only tally the reserved balance if this order waas submited
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@ func TestValidateOrderAccountIsolation(t *testing.T) {
|
|||
MaxDuration: 144,
|
||||
}
|
||||
|
||||
simpleFeeSchedule := terms.NewLinearFeeSchedule(1, 100)
|
||||
testTerms := &terms.AuctioneerTerms{
|
||||
MaxOrderDuration: 100 * MinimumOrderDurationBlocks,
|
||||
OrderExecBaseFee: 1,
|
||||
OrderExecFeeRate: 100,
|
||||
}
|
||||
|
||||
// Submitting this order for account B should pass validation.
|
||||
err := orderManager.validateOrder(
|
||||
orderB, &accountB, simpleFeeSchedule,
|
||||
)
|
||||
err := orderManager.validateOrder(orderB, &accountB, testTerms)
|
||||
if err != nil {
|
||||
t.Fatalf("order B validation failed: %v", err)
|
||||
}
|
||||
|
|
@ -82,9 +84,7 @@ func TestValidateOrderAccountIsolation(t *testing.T) {
|
|||
MaxDuration: 144,
|
||||
}
|
||||
|
||||
err = orderManager.validateOrder(
|
||||
orderA, &accountA, simpleFeeSchedule,
|
||||
)
|
||||
err = orderManager.validateOrder(orderA, &accountA, testTerms)
|
||||
if err != nil {
|
||||
t.Fatalf("order A failed validation: %v", err)
|
||||
}
|
||||
|
|
|
|||
29
rpcserver.go
29
rpcserver.go
|
|
@ -938,14 +938,16 @@ func (s *rpcServer) ListAccounts(ctx context.Context,
|
|||
|
||||
// Get the current fee schedule so we can compute the worst-case
|
||||
// account debit assuming all our standing orders were matched.
|
||||
auctionFeeSchedule, err := s.auctioneer.FeeQuote(ctx)
|
||||
terms, err := s.auctioneer.Terms(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to query auctioneer terms: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// For each active account, consume the worst-case account delta if the
|
||||
// order were to be matched.
|
||||
accountDebits := make(map[[33]byte]btcutil.Amount)
|
||||
auctionFeeSchedule := terms.FeeSchedule()
|
||||
for _, account := range accounts {
|
||||
var (
|
||||
debitAmt btcutil.Amount
|
||||
|
|
@ -1354,18 +1356,16 @@ func (s *rpcServer) SubmitOrder(ctx context.Context,
|
|||
"make order", o.Details().AcctKey[:], acct.State)
|
||||
}
|
||||
|
||||
// Get the current fee schedule to ensure we have enough balance to pay
|
||||
// the fees.
|
||||
feeSchedule, err := s.auctioneer.FeeQuote(ctx)
|
||||
// We also need to know the current maximum order duration.
|
||||
terms, err := s.auctioneer.Terms(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("could not query auctioneer terms: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// Collect all the order data and sign it before sending it to the
|
||||
// auction server.
|
||||
serverParams, err := s.orderManager.PrepareOrder(
|
||||
ctx, o, acct, feeSchedule,
|
||||
)
|
||||
serverParams, err := s.orderManager.PrepareOrder(ctx, o, acct, terms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -1691,18 +1691,19 @@ func (s *rpcServer) sendSignBatch(batch *order.Batch, sigs order.BatchSignature,
|
|||
// AuctionFee returns the current fee rate charged for matched orders within
|
||||
// the auction.
|
||||
func (s *rpcServer) AuctionFee(ctx context.Context,
|
||||
req *clmrpc.AuctionFeeRequest) (*clmrpc.AuctionFeeResponse, error) {
|
||||
_ *clmrpc.AuctionFeeRequest) (*clmrpc.AuctionFeeResponse, error) {
|
||||
|
||||
feeSchedule, err := s.auctioneer.FeeQuote(ctx)
|
||||
terms, err := s.auctioneer.Terms(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to query auctioneer terms: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// TODO(roasbeef): accept the amt of order instead?
|
||||
return &clmrpc.AuctionFeeResponse{
|
||||
ExecutionFee: &clmrpc.ExecutionFee{
|
||||
BaseFee: uint64(feeSchedule.BaseFee()),
|
||||
FeeRate: uint64(feeSchedule.FeeRate()),
|
||||
BaseFee: uint64(terms.OrderExecBaseFee),
|
||||
FeeRate: uint64(terms.OrderExecFeeRate),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue