mirror of
https://github.com/lightninglabs/pool.git
synced 2026-08-13 12:33:04 +02:00
multi: update order/batch verification for outbound liquidity auctions
This commit is contained in:
parent
34bbd1ec3f
commit
e5d78fd3cb
11 changed files with 207 additions and 81 deletions
|
|
@ -721,8 +721,9 @@ func parseBaseBid(ctx *cli.Context) (*poolrpc.Bid, *sidecar.Ticket, error) {
|
|||
if ctx.IsSet("self_chan_balance") {
|
||||
bid.SelfChanBalance = ctx.Uint64("self_chan_balance")
|
||||
bidAmt := btcutil.Amount(bid.Details.Amt)
|
||||
err := sidecar.CheckOfferParams(
|
||||
bidAmt, btcutil.Amount(bid.SelfChanBalance),
|
||||
err := order.CheckOfferParams(
|
||||
order.AuctionType(bid.Details.AuctionType), bidAmt,
|
||||
btcutil.Amount(bid.SelfChanBalance),
|
||||
order.BaseSupplyUnit,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1023,8 +1023,15 @@ func (m *Manager) OfferSidecar(ctx context.Context, capacity,
|
|||
acctPubKey *keychain.KeyDescriptor,
|
||||
bid *order.Bid, auto bool) (*sidecar.Ticket, error) {
|
||||
|
||||
if bid.Details().AuctionType != order.BTCInboundLiquidity {
|
||||
return nil, fmt.Errorf("%s market does not support sidecar "+
|
||||
"tickets", bid.Details().AuctionType)
|
||||
}
|
||||
|
||||
// Make sure the capacity and push amounts are sane.
|
||||
err := sidecar.CheckOfferParams(capacity, pushAmt, order.BaseSupplyUnit)
|
||||
err := order.CheckOfferParams(
|
||||
bid.AuctionType, capacity, pushAmt, order.BaseSupplyUnit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -805,28 +805,66 @@ func TestOfferSidecarValidation(t *testing.T) {
|
|||
name string
|
||||
capacity btcutil.Amount
|
||||
pushAmt btcutil.Amount
|
||||
bid *order.Bid
|
||||
expectedErr string
|
||||
}{{
|
||||
name: "empty capacity",
|
||||
bid: &order.Bid{},
|
||||
expectedErr: "channel capacity must be positive multiple of",
|
||||
}, {
|
||||
name: "invalid capacity",
|
||||
capacity: 123,
|
||||
bid: &order.Bid{},
|
||||
expectedErr: "channel capacity must be positive multiple of",
|
||||
}, {
|
||||
name: "invalid push amount",
|
||||
capacity: 100000,
|
||||
pushAmt: 100001,
|
||||
bid: &order.Bid{},
|
||||
expectedErr: "self channel balance must be smaller than " +
|
||||
"or equal to capacity",
|
||||
}, {
|
||||
name: "no sidecar for outbound market",
|
||||
capacity: 100000,
|
||||
pushAmt: 0,
|
||||
bid: &order.Bid{
|
||||
Kit: order.Kit{
|
||||
AuctionType: order.BTCOutboundLiquidity,
|
||||
},
|
||||
},
|
||||
expectedErr: "market does not support sidecar tickets",
|
||||
}}
|
||||
|
||||
privKey, err := btcec.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
desc := &keychain.KeyDescriptor{
|
||||
PubKey: privKey.PubKey(),
|
||||
}
|
||||
|
||||
// We'll need a formally valid signature to pass the parsing. So we'll
|
||||
// just create a dummy signature from a random key pair.
|
||||
hash := sha256.New()
|
||||
_, _ = hash.Write([]byte("foo"))
|
||||
digest := hash.Sum(nil)
|
||||
sig := ecdsa.Sign(privKey, digest)
|
||||
|
||||
h.mgr.cfg.NodePubKey = privKey.PubKey()
|
||||
h.signerMock.Signature = sig.Serialize()
|
||||
var nodeKeyRaw [33]byte
|
||||
copy(nodeKeyRaw[:], privKey.PubKey().SerializeCompressed())
|
||||
|
||||
for _, testCase := range negativeCases {
|
||||
_, err := h.mgr.OfferSidecar(
|
||||
context.Background(), testCase.capacity,
|
||||
testCase.pushAmt, 2016, nil, nil, false,
|
||||
testCase.pushAmt, 2016, desc, testCase.bid, false,
|
||||
)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), testCase.expectedErr)
|
||||
fmt.Println(testCase.expectedErr)
|
||||
if testCase.expectedErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), testCase.expectedErr)
|
||||
continue
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,11 @@ func (v *batchVerifier) Verify(batch *Batch, bestHeight uint32) error {
|
|||
),
|
||||
}
|
||||
|
||||
case unitsFilled < ourOrder.Details().MinUnitsMatch:
|
||||
// For the BTCOutboundLiquidity market exactly one unit will be
|
||||
// matched.
|
||||
case ourOrder.Details().AuctionType != BTCOutboundLiquidity &&
|
||||
unitsFilled < ourOrder.Details().MinUnitsMatch:
|
||||
|
||||
return &MismatchErr{
|
||||
msg: fmt.Sprintf("invalid units to be filled "+
|
||||
"for order %v. matched %d units, but "+
|
||||
|
|
@ -283,6 +287,13 @@ func (v *batchVerifier) validateMatchedOrder(tally *AccountTally,
|
|||
"orders", ourOrder.Nonce())
|
||||
}
|
||||
|
||||
// Auction types must match.
|
||||
auctionType := ourOrder.Details().AuctionType
|
||||
if auctionType != otherOrder.Order.Details().AuctionType {
|
||||
return fmt.Errorf("order %v did not match the same auction "+
|
||||
"type", ourOrder.Nonce())
|
||||
}
|
||||
|
||||
// Make sure we weren't matched to our own order.
|
||||
if otherOrder.NodeKey == v.ourNodePubkey {
|
||||
return fmt.Errorf("other order is an order from our node")
|
||||
|
|
@ -305,10 +316,15 @@ func (v *batchVerifier) validateMatchedOrder(tally *AccountTally,
|
|||
return fmt.Errorf("ask price greater than bid price")
|
||||
}
|
||||
|
||||
makerAmt := otherOrder.UnitsFilled.ToSatoshis()
|
||||
premiumAmt := makerAmt
|
||||
if auctionType == BTCOutboundLiquidity {
|
||||
premiumAmt += other.SelfChanBalance
|
||||
}
|
||||
|
||||
// This match checks out, deduct it from the account's balance.
|
||||
tally.CalcMakerDelta(
|
||||
executionFee, clearingPrice,
|
||||
otherOrder.UnitsFilled.ToSatoshis(),
|
||||
executionFee, clearingPrice, makerAmt, premiumAmt,
|
||||
other.LeaseDuration,
|
||||
)
|
||||
|
||||
|
|
@ -324,11 +340,16 @@ func (v *batchVerifier) validateMatchedOrder(tally *AccountTally,
|
|||
return fmt.Errorf("ask price greater than bid price")
|
||||
}
|
||||
|
||||
takerAmt := ours.SelfChanBalance
|
||||
premiumAmt := otherOrder.UnitsFilled.ToSatoshis()
|
||||
if auctionType == BTCOutboundLiquidity {
|
||||
premiumAmt += takerAmt
|
||||
}
|
||||
|
||||
// This match checks out, deduct it from the account's balance.
|
||||
tally.CalcTakerDelta(
|
||||
executionFee, clearingPrice,
|
||||
otherOrder.UnitsFilled.ToSatoshis(),
|
||||
ours.SelfChanBalance, ours.LeaseDuration,
|
||||
executionFee, clearingPrice, takerAmt, premiumAmt,
|
||||
ours.LeaseDuration,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -358,6 +358,40 @@ func TestBatchVerifier(t *testing.T) {
|
|||
return v.Verify(b, bestHeight)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "auction type mismatch",
|
||||
expectedErr: "did not match the same auction type",
|
||||
doVerify: func(v BatchVerifier, a *Ask, b1, b2 *Bid,
|
||||
b *Batch) error {
|
||||
|
||||
a.Details().AuctionType = BTCInboundLiquidity
|
||||
b1.Details().AuctionType = BTCOutboundLiquidity
|
||||
return v.Verify(b, bestHeight)
|
||||
},
|
||||
},
|
||||
{
|
||||
// TODO(positiveblue): make a more specific test for
|
||||
// btc outbound liquidity market.
|
||||
name: "premiums are based on aucton type",
|
||||
expectedErr: "ending balance 934",
|
||||
doVerify: func(v BatchVerifier, a *Ask, b1, b2 *Bid,
|
||||
b *Batch) error {
|
||||
|
||||
a.Details().AuctionType = BTCOutboundLiquidity
|
||||
b1.Details().AuctionType = BTCOutboundLiquidity
|
||||
b2.Details().AuctionType = BTCOutboundLiquidity
|
||||
b.AccountDiffs[0].EndingBalance = 395_089
|
||||
b.BatchTX.TxOut[2].Value = 395_089
|
||||
|
||||
// NOTE: the ask and bids would not be valid
|
||||
// orders for the outbound liquidity market
|
||||
// because they bigger than one unit but we are
|
||||
// testing that premiums are calculated
|
||||
// properly here.
|
||||
b.AccountDiffs[1].EndingBalance = 934
|
||||
return v.Verify(b, bestHeight)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Run through all the test cases, creating a new, valid batch each
|
||||
|
|
@ -430,7 +464,7 @@ func TestBatchVerifier(t *testing.T) {
|
|||
// 2000 * (200_000 * 5000 / 1_000_000_000) = 1000 sats premium
|
||||
LeaseDuration: leaseDuration,
|
||||
}),
|
||||
SelfChanBalance: 50,
|
||||
SelfChanBalance: 100_000,
|
||||
}
|
||||
pkScript := scriptForAcct(t, bigAcct)
|
||||
// If account extension is supported we create the pkScript with
|
||||
|
|
@ -456,7 +490,7 @@ func TestBatchVerifier(t *testing.T) {
|
|||
// Channel output for channel between ask and
|
||||
// bid2.
|
||||
{
|
||||
Value: 200_050,
|
||||
Value: 300_000,
|
||||
PkScript: scriptForChan(
|
||||
t, walletKit,
|
||||
ask.MultiSigKeyLocator,
|
||||
|
|
@ -469,8 +503,8 @@ func TestBatchVerifier(t *testing.T) {
|
|||
// bid1ExecFee - bid2ExecFee - chainFees
|
||||
// - bid2SelfChanBalance
|
||||
// 500_000 - 1000 - 1000 -
|
||||
// 1_110 - 1_110 - 186 - 50
|
||||
Value: 495_544,
|
||||
// 1_110 - 1_110 - 186 - 100_000
|
||||
Value: 395_594,
|
||||
PkScript: pkScript,
|
||||
},
|
||||
},
|
||||
|
|
@ -485,7 +519,7 @@ func TestBatchVerifier(t *testing.T) {
|
|||
AccountKey: acctKeyBig,
|
||||
EndingState: stateRecreated,
|
||||
OutpointIndex: 2,
|
||||
EndingBalance: 495_544,
|
||||
EndingBalance: 395_594,
|
||||
},
|
||||
{
|
||||
AccountKeyRaw: acctIDSmall,
|
||||
|
|
|
|||
|
|
@ -639,7 +639,7 @@ func (a *Ask) ReservedValue(feeSchedule terms.FeeSchedule,
|
|||
|
||||
return reservedValue(a, func(amt btcutil.Amount) btcutil.Amount {
|
||||
delta, _, _ := makerDelta(
|
||||
feeSchedule, clearingPrice, amt, a.LeaseDuration,
|
||||
feeSchedule, clearingPrice, amt, amt, a.LeaseDuration,
|
||||
)
|
||||
return delta
|
||||
}, accountVersion)
|
||||
|
|
@ -823,14 +823,77 @@ func (b *Bid) ReservedValue(feeSchedule terms.FeeSchedule,
|
|||
clearingPrice := FixedRatePremium(b.FixedRate)
|
||||
|
||||
return reservedValue(b, func(amt btcutil.Amount) btcutil.Amount {
|
||||
premiumAmt := amt
|
||||
if b.Details().AuctionType == BTCOutboundLiquidity {
|
||||
premiumAmt += b.SelfChanBalance
|
||||
}
|
||||
|
||||
delta, _, _ := takerDelta(
|
||||
feeSchedule, clearingPrice, amt, b.SelfChanBalance,
|
||||
b.LeaseDuration,
|
||||
feeSchedule, clearingPrice, premiumAmt,
|
||||
b.SelfChanBalance, b.LeaseDuration,
|
||||
)
|
||||
return delta
|
||||
}, accountVersion)
|
||||
}
|
||||
|
||||
// CheckOfferParams makes sure the offer parameters of an offer are valid and
|
||||
// sane.
|
||||
func CheckOfferParams(auctionType AuctionType, capacity, pushAmt,
|
||||
baseSupplyUnit btcutil.Amount) error {
|
||||
|
||||
if capacity == 0 || capacity%baseSupplyUnit != 0 {
|
||||
return fmt.Errorf("channel capacity must be positive multiple "+
|
||||
"of %d", baseSupplyUnit)
|
||||
}
|
||||
|
||||
if auctionType == BTCInboundLiquidity && pushAmt > capacity {
|
||||
return fmt.Errorf("self channel balance must be smaller than " +
|
||||
"or equal to capacity")
|
||||
}
|
||||
|
||||
if auctionType == BTCOutboundLiquidity {
|
||||
// Only multiples of 100k sats are allowed in the outbound
|
||||
// market.
|
||||
if pushAmt == 0 || pushAmt%baseSupplyUnit != 0 {
|
||||
return fmt.Errorf("self balance must be a positive "+
|
||||
"multiple of %d", baseSupplyUnit)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckOfferParamsForOrder makes sure that the order parameters in a
|
||||
// sidecar offer are formally valid, sane and match the order parameters.
|
||||
func CheckOfferParamsForOrder(auctionType AuctionType, offer sidecar.Offer,
|
||||
bidAmt, bidMinUnitsMatch, baseSupplyUnit btcutil.Amount) error {
|
||||
|
||||
if auctionType != BTCInboundLiquidity {
|
||||
return fmt.Errorf("%s market does not support sidecar tickets",
|
||||
auctionType)
|
||||
}
|
||||
|
||||
err := CheckOfferParams(
|
||||
auctionType, offer.Capacity, offer.PushAmt, baseSupplyUnit,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if offer.Capacity != bidAmt {
|
||||
return fmt.Errorf("invalid bid amount %v, must match sidecar "+
|
||||
"ticket's capacity %v", bidAmt, offer.Capacity)
|
||||
}
|
||||
|
||||
if offer.Capacity != bidMinUnitsMatch*baseSupplyUnit {
|
||||
return fmt.Errorf("invalid min units match %v, must match "+
|
||||
"sidecar ticket's capacity %v",
|
||||
bidMinUnitsMatch*baseSupplyUnit, offer.Capacity)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateSelfChanBalance makes sure that all conditions to use the
|
||||
// SelfChanBalance field on a bid order are met.
|
||||
func (b *Bid) ValidateSelfChanBalance() error {
|
||||
|
|
@ -839,8 +902,8 @@ func (b *Bid) ValidateSelfChanBalance() error {
|
|||
"order version")
|
||||
}
|
||||
|
||||
if err := sidecar.CheckOfferParams(
|
||||
b.Amt, b.SelfChanBalance, BaseSupplyUnit,
|
||||
if err := CheckOfferParams(
|
||||
b.AuctionType, b.Amt, b.SelfChanBalance, BaseSupplyUnit,
|
||||
); err != nil {
|
||||
return fmt.Errorf("invalid self chan balance: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestOrderReservedValue checks orders' ReservedValue merhod returning the
|
||||
// TestOrderReservedValue checks orders' ReservedValue method returning the
|
||||
// expected worst case value.
|
||||
func TestOrderReservedValue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
@ -240,7 +240,7 @@ func TestOrderReservedValue(t *testing.T) {
|
|||
1, o.MaxBatchFeeRate, v,
|
||||
)
|
||||
|
||||
// For bids the lump sum, chain fee and the
|
||||
// For bids the lump sum, chain fee and the
|
||||
// execution fee must be reserved.
|
||||
expValue += lumpSum + chainFee + exeFee
|
||||
}
|
||||
|
|
|
|||
|
|
@ -465,8 +465,9 @@ func (m *manager) validateAndSignTicketForOrder(ctx context.Context,
|
|||
|
||||
// The signature is valid! Let's now make sure the offer and the order
|
||||
// parameters actually match.
|
||||
err := sidecar.CheckOfferParamsForOrder(
|
||||
o, bid.Amt, btcutil.Amount(bid.MinUnitsMatch), BaseSupplyUnit,
|
||||
err := CheckOfferParamsForOrder(
|
||||
bid.AuctionType, o, bid.Amt, btcutil.Amount(bid.MinUnitsMatch),
|
||||
BaseSupplyUnit,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ func ParseRPCOrder(version, leaseDuration uint32,
|
|||
return nil, errors.New("min units match must be greater than 0")
|
||||
|
||||
// The min units match must not exceed the total order units.
|
||||
case details.MinUnitsMatch > uint32(kit.Units):
|
||||
case kit.AuctionType != BTCOutboundLiquidity &&
|
||||
details.MinUnitsMatch > uint32(kit.Units):
|
||||
|
||||
return nil, errors.New("min units match must not exceed " +
|
||||
"total order units")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,23 +174,23 @@ type AccountTally struct {
|
|||
// order where the account is involved on the maker side. It returns the
|
||||
// balance delta, fees accrued, and execution fee paid.
|
||||
func makerDelta(feeSchedule terms.FeeSchedule, price FixedRatePremium,
|
||||
totalSats btcutil.Amount, duration uint32) (btcutil.Amount,
|
||||
makerAmt, baseAmt btcutil.Amount, duration uint32) (btcutil.Amount,
|
||||
btcutil.Amount, btcutil.Amount) {
|
||||
|
||||
// First, we'll need to subtract the total amount of sats cleared (the
|
||||
// First, we'll need to subtract the total matched amount (the
|
||||
// channel size), from the balance of the maker.
|
||||
balanceDelta := -totalSats
|
||||
balanceDelta := -makerAmt
|
||||
|
||||
// Calculate the premium based on the duration the capital will be
|
||||
// locked for.
|
||||
satsPremium := price.LumpSumPremium(totalSats, duration)
|
||||
satsPremium := price.LumpSumPremium(baseAmt, duration)
|
||||
|
||||
// The premium is paid to the maker.
|
||||
balanceDelta += satsPremium
|
||||
makerFeesAccrued := satsPremium
|
||||
|
||||
// Finally, we'll subtract the paid execution fees from the balance.
|
||||
executionFee := executionFee(totalSats, feeSchedule)
|
||||
executionFee := executionFee(makerAmt, feeSchedule)
|
||||
balanceDelta -= executionFee
|
||||
|
||||
return balanceDelta, makerFeesAccrued, executionFee
|
||||
|
|
@ -200,12 +200,12 @@ func makerDelta(feeSchedule terms.FeeSchedule, price FixedRatePremium,
|
|||
// 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 terms.FeeSchedule,
|
||||
price FixedRatePremium, totalSats btcutil.Amount,
|
||||
price FixedRatePremium, makerAmt, premiumAmt btcutil.Amount,
|
||||
duration uint32) btcutil.Amount {
|
||||
|
||||
// Calculate the deltas and update the tally.
|
||||
balanceDelta, makerFeesAccrued, executionFee := makerDelta(
|
||||
feeSchedule, price, totalSats, duration,
|
||||
feeSchedule, price, makerAmt, premiumAmt, duration,
|
||||
)
|
||||
|
||||
t.EndingBalance += balanceDelta
|
||||
|
|
@ -219,12 +219,12 @@ func (t *AccountTally) CalcMakerDelta(feeSchedule terms.FeeSchedule,
|
|||
// 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 terms.FeeSchedule,
|
||||
price FixedRatePremium, totalSats, selfChanBalance btcutil.Amount,
|
||||
price FixedRatePremium, baseAmt, takerAmt btcutil.Amount,
|
||||
duration uint32) (btcutil.Amount, btcutil.Amount, btcutil.Amount) {
|
||||
|
||||
// Calculate the premium based on the duration the capital will be
|
||||
// locked for.
|
||||
satsPremium := price.LumpSumPremium(totalSats, duration)
|
||||
satsPremium := price.LumpSumPremium(baseAmt, duration)
|
||||
|
||||
// The premium must be paid by the taker.
|
||||
balanceDelta := -satsPremium
|
||||
|
|
@ -232,10 +232,10 @@ func takerDelta(feeSchedule terms.FeeSchedule,
|
|||
|
||||
// If there is a self channel balance, it must also be paid out of the
|
||||
// taker account.
|
||||
balanceDelta -= selfChanBalance
|
||||
balanceDelta -= takerAmt
|
||||
|
||||
// Finally, we'll subtract the paid execution fees from the balance.
|
||||
executionFee := executionFee(totalSats, feeSchedule)
|
||||
executionFee := executionFee(baseAmt, feeSchedule)
|
||||
balanceDelta -= executionFee
|
||||
|
||||
return balanceDelta, takerFeesPaid, executionFee
|
||||
|
|
@ -245,12 +245,12 @@ func takerDelta(feeSchedule terms.FeeSchedule,
|
|||
// 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 terms.FeeSchedule,
|
||||
price FixedRatePremium, totalSats, selfChanBalance btcutil.Amount,
|
||||
price FixedRatePremium, takerAmt, premiumAmt btcutil.Amount,
|
||||
duration uint32) btcutil.Amount {
|
||||
|
||||
// Calculate the deltas and update the tally.
|
||||
balanceDelta, takerFeesPaid, executionFee := takerDelta(
|
||||
feeSchedule, price, totalSats, selfChanBalance, duration,
|
||||
feeSchedule, price, premiumAmt, takerAmt, duration,
|
||||
)
|
||||
|
||||
t.EndingBalance += balanceDelta
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
|
|
@ -184,43 +183,3 @@ func VerifyOrder(ctx context.Context, ticket *Ticket,
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckOfferParams makes sure the offer parameters of a sidecar ticket are
|
||||
// valid and sane.
|
||||
func CheckOfferParams(capacity, pushAmt, baseSupplyUnit btcutil.Amount) error {
|
||||
if capacity == 0 || capacity%baseSupplyUnit != 0 {
|
||||
return fmt.Errorf("channel capacity must be positive multiple "+
|
||||
"of %d", baseSupplyUnit)
|
||||
}
|
||||
|
||||
if pushAmt > capacity {
|
||||
return fmt.Errorf("self channel balance must be smaller than " +
|
||||
"or equal to capacity")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckOfferParamsForOrder makes sure that the order parameters in a
|
||||
// sidecar offer are formally valid, sane and match the order parameters.
|
||||
func CheckOfferParamsForOrder(offer Offer, bidAmt, bidMinUnitsMatch,
|
||||
baseSupplyUnit btcutil.Amount) error {
|
||||
|
||||
err := CheckOfferParams(offer.Capacity, offer.PushAmt, baseSupplyUnit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if offer.Capacity != bidAmt {
|
||||
return fmt.Errorf("invalid bid amount %v, must match sidecar "+
|
||||
"ticket's capacity %v", bidAmt, offer.Capacity)
|
||||
}
|
||||
|
||||
if offer.Capacity != bidMinUnitsMatch*baseSupplyUnit {
|
||||
return fmt.Errorf("invalid min units match %v, must match "+
|
||||
"sidecar ticket's capacity %v",
|
||||
bidMinUnitsMatch*baseSupplyUnit, offer.Capacity)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue