lnrpc+routerrpc+lncli: add allow_self_payments safety flag

This commit is contained in:
Joost Jager
2019-11-25 14:13:21 +01:00
parent f8e9efbf99
commit 2d19201ede
8 changed files with 759 additions and 689 deletions

View File

@@ -487,6 +487,9 @@ type rpcServer struct {
// macService is the macaroon service that we need to mint new
// macaroons.
macService *macaroons.Service
// selfNode is our own pubkey.
selfNode route.Vertex
}
// A compile time check to ensure that rpcServer fully implements the
@@ -662,6 +665,7 @@ func newRPCServer(s *server, macService *macaroons.Service,
chanPredicate: chanPredicate,
quit: make(chan struct{}, 1),
macService: macService,
selfNode: selfNode.PubKeyBytes,
}
lnrpc.RegisterLightningServer(grpcServer, rootRPCServer)
@@ -3079,7 +3083,7 @@ type rpcPaymentIntent struct {
// dispatch a client from the information presented by an RPC client. There are
// three ways a client can specify their payment details: a payment request,
// via manual details, or via a complete route.
func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error) {
func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error) {
payIntent := rpcPaymentIntent{}
// If a route was specified, then we can use that directly.
@@ -3139,6 +3143,18 @@ func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error
}
}
validateDest := func(dest route.Vertex) error {
if rpcPayReq.AllowSelfPayment {
return nil
}
if dest == r.selfNode {
return errors.New("self-payments not allowed")
}
return nil
}
// If the payment request field isn't blank, then the details of the
// invoice are encoded entirely within the encoded payReq. So we'll
// attempt to decode it, populating the payment accordingly.
@@ -3190,6 +3206,10 @@ func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error
payIntent.routeHints = payReq.RouteHints
payIntent.payReq = []byte(rpcPayReq.PaymentRequest)
if err := validateDest(payIntent.dest); err != nil {
return payIntent, err
}
return payIntent, nil
}
@@ -3211,6 +3231,10 @@ func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error
}
copy(payIntent.dest[:], pubBytes)
if err := validateDest(payIntent.dest); err != nil {
return payIntent, err
}
// Otherwise, If the payment request field was not specified
// (and a custom route wasn't specified), construct the payment
// from the other fields.
@@ -3401,7 +3425,9 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
// fields. If the payment proto wasn't well
// formed, then we'll send an error reply and
// wait for the next payment.
payIntent, err := extractPaymentIntent(nextPayment)
payIntent, err := r.extractPaymentIntent(
nextPayment,
)
if err != nil {
if err := stream.send(&lnrpc.SendResponse{
PaymentError: err.Error(),
@@ -3540,7 +3566,7 @@ func (r *rpcServer) sendPaymentSync(ctx context.Context,
// First we'll attempt to map the proto describing the next payment to
// an intent that we can pass to local sub-systems.
payIntent, err := extractPaymentIntent(nextPayment)
payIntent, err := r.extractPaymentIntent(nextPayment)
if err != nil {
return nil, err
}