Skip to content

Commit bad508d

Browse files
committed
rpcserver: AddInvoice uses new helper methods
1 parent 0c548de commit bad508d

File tree

1 file changed

+11
-118
lines changed

1 file changed

+11
-118
lines changed

rpcserver.go

Lines changed: 11 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -7717,13 +7717,6 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
77177717
"amount")
77187718
}
77197719

7720-
// In order to avoid repeating the following check let's assign it to a
7721-
// boolean for easier access.
7722-
var satsMode bool
7723-
if amtMsat != 0 {
7724-
satsMode = true
7725-
}
7726-
77277720
// The peer public key is optional if there is only a single asset
77287721
// channel.
77297722
var peerPubKey *route.Vertex
@@ -7758,60 +7751,14 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
77587751
time.Duration(expirySeconds) * time.Second,
77597752
)
77607753

7761-
maxUnits := req.AssetAmount
7762-
7763-
// If the invoice defines the desired amount in satoshis, we need to
7764-
// query our oracle first to get an estimation on the asset rate. This
7765-
// will help us establish a quote with the correct amount of asset
7766-
// units.
7767-
if satsMode {
7768-
oracleRes, err := r.cfg.PriceOracle.QueryBidPrice(
7769-
ctx, specifier, fn.None[uint64](), fn.Some(amtMsat),
7770-
fn.None[rfqmsg.AssetRate](),
7771-
)
7772-
if err != nil {
7773-
return nil, err
7774-
}
7775-
7776-
if oracleRes.Err != nil {
7777-
return nil, fmt.Errorf("cannot query oracle: %v",
7778-
oracleRes.Err.Error())
7779-
}
7780-
7781-
assetUnits := rfqmath.MilliSatoshiToUnits(
7782-
amtMsat, oracleRes.AssetRate.Rate,
7783-
)
7784-
7785-
maxUnits = assetUnits.ToUint64()
7786-
}
7787-
7788-
// Since we used a different oracle price query above calculate the max
7789-
// amount of units, we want to add some breathing room to account for
7790-
// price fluctuations caused by the small time delay, plus the fact that
7791-
// the agreed upon quote may be different. If we don't add this safety
7792-
// window the peer may allow a routable amount that evaluates to less
7793-
// than what we ask for.
7794-
tolerance := rfqmath.NewBigIntFromUint64(
7754+
maxUnits, err := calculateAssetMaxAmount(
7755+
ctx, r.cfg.PriceOracle, specifier, req.AssetAmount, iReq,
77957756
r.cfg.RfqManager.GetPriceDeviationPpm(),
77967757
)
7797-
7798-
// Parse the max asset units to the rfqmath type.
7799-
maxMathUnits := rfqmath.NewBigIntFromUint64(maxUnits)
7800-
7801-
// Calculate the tolerance margin.
7802-
toleranceUnits := maxMathUnits.Mul(tolerance).Div(
7803-
rfqmath.NewBigIntFromUint64(1_000_000),
7804-
)
7805-
7806-
// Apply the tolerance margin twice. Once due to the ask/bid price
7807-
// deviation that may occur during rfq negotiation, and once for the
7808-
// price movement that may occur between querying the oracle and
7809-
// acquiring the quote. We don't really care about this margin being too
7810-
// big, this only affects the max units our peer agrees to route.
7811-
maxMathUnits = maxMathUnits.Add(toleranceUnits).Add(toleranceUnits)
7812-
7813-
// Now parse the result back to uint64.
7814-
maxUnits = maxMathUnits.ToUint64()
7758+
if err != nil {
7759+
return nil, fmt.Errorf("error calculating asset max "+
7760+
"amount: %w", err)
7761+
}
78157762

78167763
rpcSpecifier := marshalAssetSpecifier(specifier)
78177764

@@ -7847,68 +7794,14 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
78477794
return nil, fmt.Errorf("unexpected response type: %T", r)
78487795
}
78497796

7850-
// Now that we have the accepted quote, we know the amount in Satoshi
7851-
// that we need to pay. We can now update the invoice with this amount.
7852-
//
7853-
// First, un-marshall the ask asset rate from the accepted quote.
7854-
askAssetRate, err := rfqrpc.UnmarshalFixedPoint(
7855-
acceptedQuote.AskAssetRate,
7797+
invoiceAmtMsat, err := validateInvoiceAmount(
7798+
acceptedQuote, req.AssetAmount, iReq,
78567799
)
78577800
if err != nil {
7858-
return nil, fmt.Errorf("error unmarshalling ask asset rate: %w",
7859-
err)
7860-
}
7861-
7862-
invUnits := req.AssetAmount
7863-
7864-
if satsMode {
7865-
// If the invoice was created over a satoshi amount, we need to
7866-
// calculate the units.
7867-
invUnits = rfqmath.MilliSatoshiToUnits(
7868-
amtMsat, *askAssetRate,
7869-
).ScaleTo(0).ToUint64()
7870-
7871-
// Now let's see if the negotiated quote can actually route the
7872-
// amount we need in msat.
7873-
maxFixedUnits := rfqmath.NewBigIntFixedPoint(
7874-
acceptedQuote.AssetMaxAmount, 0,
7875-
)
7876-
maxRoutableMsat := rfqmath.UnitsToMilliSatoshi(
7877-
maxFixedUnits, *askAssetRate,
7878-
)
7879-
7880-
if maxRoutableMsat <= amtMsat {
7881-
return nil, fmt.Errorf("cannot create invoice for %v "+
7882-
"msat, max routable amount is %v msat", amtMsat,
7883-
maxRoutableMsat)
7884-
}
7885-
}
7886-
7887-
// If the invoice is for an asset unit amount smaller than the minimal
7888-
// transportable amount, we'll return an error, as it wouldn't be
7889-
// payable by the network.
7890-
if acceptedQuote.MinTransportableUnits > invUnits {
7891-
return nil, fmt.Errorf("cannot create invoice over %d asset "+
7892-
"units, as the minimal transportable amount is %d "+
7893-
"units with the current rate of %v units/BTC",
7894-
invUnits, acceptedQuote.MinTransportableUnits,
7895-
acceptedQuote.AskAssetRate)
7896-
}
7897-
7898-
switch {
7899-
case satsMode:
7900-
iReq.ValueMsat = int64(amtMsat)
7901-
7902-
default:
7903-
// Convert the asset amount into a fixed-point.
7904-
assetAmount := rfqmath.NewBigIntFixedPoint(req.AssetAmount, 0)
7905-
7906-
// Calculate the invoice amount in msat.
7907-
valMsat := rfqmath.UnitsToMilliSatoshi(
7908-
assetAmount, *askAssetRate,
7909-
)
7910-
iReq.ValueMsat = int64(valMsat)
7801+
return nil, fmt.Errorf("error validating invoice "+
7802+
"amount: %w", err)
79117803
}
7804+
iReq.ValueMsat = invoiceAmtMsat
79127805

79137806
// The last step is to create a hop hint that includes the fake SCID of
79147807
// the quote, alongside the channel's routing policy. We need to choose

0 commit comments

Comments
 (0)