From 8392f6d28f1415f9fee2f7fbbb97f7afa589c565 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 15 Jan 2019 10:06:48 +0100 Subject: [PATCH] lnrpc/invoicesrpc: remove lnrpc type from add invoice --- channeldb/invoices.go | 7 +- invoices/invoiceregistry.go | 3 +- lnrpc/invoicesrpc/addinvoice.go | 109 +++++++++++++++++++------------- rpcserver.go | 33 +++++++++- 4 files changed, 102 insertions(+), 50 deletions(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 257a7cb6..8584252f 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -213,10 +213,11 @@ func validateInvoice(i *Invoice) error { return nil } -// AddInvoice inserts the targeted invoice into the database. If the invoice -// has *any* payment hashes which already exists within the database, then the +// AddInvoice inserts the targeted invoice into the database. If the invoice has +// *any* payment hashes which already exists within the database, then the // insertion will be aborted and rejected due to the strict policy banning any -// duplicate payment hashes. +// duplicate payment hashes. A side effect of this function is that it sets +// AddIndex on newInvoice. func (d *DB) AddInvoice(newInvoice *Invoice) (uint64, error) { if err := validateInvoice(newInvoice); err != nil { return 0, err diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 31c81bc6..88111820 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -380,7 +380,8 @@ func (i *InvoiceRegistry) AddDebugInvoice(amt btcutil.Amount, // daemon add/forward HTLCs are able to obtain the proper preimage required for // redemption in the case that we're the final destination. We also return the // addIndex of the newly created invoice which monotonically increases for each -// new invoice added. +// new invoice added. A side effect of this function is that it also sets +// AddIndex on the invoice argument. func (i *InvoiceRegistry) AddInvoice(invoice *channeldb.Invoice, paymentHash lntypes.Hash) (uint64, error) { diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index f4171d20..42b79cbd 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "crypto/rand" - "crypto/sha256" "fmt" "math" "time" @@ -17,7 +16,6 @@ import ( "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" ) @@ -50,70 +48,95 @@ type AddInvoiceConfig struct { ChanDB *channeldb.DB } +// AddInvoiceData contains the required data to create a new invoice. +type AddInvoiceData struct { + // An optional memo to attach along with the invoice. Used for record + // keeping purposes for the invoice's creator, and will also be set in + // the description field of the encoded payment request if the + // description_hash field is not being used. + Memo string + + // Deprecated. An optional cryptographic receipt of payment which is not + // implemented. + Receipt []byte + + // The preimage which will allow settling an incoming HTLC payable to + // this preimage. + Preimage *lntypes.Preimage + + // The value of this invoice in satoshis. + Value btcutil.Amount + + // Hash (SHA-256) of a description of the payment. Used if the + // description of payment (memo) is too long to naturally fit within the + // description field of an encoded payment request. + DescriptionHash []byte + + // Payment request expiry time in seconds. Default is 3600 (1 hour). + Expiry int64 + + // Fallback on-chain address. + FallbackAddr string + + // Delta to use for the time-lock of the CLTV extended to the final hop. + CltvExpiry uint64 + + // Whether this invoice should include routing hints for private + // channels. + Private bool +} + // AddInvoice attempts to add a new invoice to the invoice database. Any -// duplicated invoices are rejected, therefore all invoices *must* have a -// unique payment preimage. +// duplicated invoices are rejected, therefore all invoices *must* have a unique +// payment preimage. AddInvoice returns the payment hash and the invoice +// structure as stored in the database. func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, - invoice *lnrpc.Invoice) (*lnrpc.AddInvoiceResponse, error) { + invoice *AddInvoiceData) (*lntypes.Hash, *channeldb.Invoice, error) { - var paymentPreimage [32]byte - - switch { - // If a preimage wasn't specified, then we'll generate a new preimage - // from fresh cryptographic randomness. - case len(invoice.RPreimage) == 0: + var paymentPreimage lntypes.Preimage + if invoice.Preimage == nil { if _, err := rand.Read(paymentPreimage[:]); err != nil { - return nil, err + return nil, nil, err } - - // Otherwise, if a preimage was specified, then it MUST be exactly - // 32-bytes. - case len(invoice.RPreimage) != 32: - return nil, fmt.Errorf("payment preimage must be exactly "+ - "32 bytes, is instead %v", len(invoice.RPreimage)) - - // If the preimage meets the size specifications, then it can be used - // as is. - default: - copy(paymentPreimage[:], invoice.RPreimage[:]) + } else { + paymentPreimage = *invoice.Preimage } // The size of the memo, receipt and description hash attached must not // exceed the maximum values for either of the fields. if len(invoice.Memo) > channeldb.MaxMemoSize { - return nil, fmt.Errorf("memo too large: %v bytes "+ + return nil, nil, fmt.Errorf("memo too large: %v bytes "+ "(maxsize=%v)", len(invoice.Memo), channeldb.MaxMemoSize) } if len(invoice.Receipt) > channeldb.MaxReceiptSize { - return nil, fmt.Errorf("receipt too large: %v bytes "+ + return nil, nil, fmt.Errorf("receipt too large: %v bytes "+ "(maxsize=%v)", len(invoice.Receipt), channeldb.MaxReceiptSize) } if len(invoice.DescriptionHash) > 0 && len(invoice.DescriptionHash) != 32 { - return nil, fmt.Errorf("description hash is %v bytes, must be %v", + return nil, nil, fmt.Errorf("description hash is %v bytes, must be %v", len(invoice.DescriptionHash), channeldb.MaxPaymentRequestSize) } // The value of the invoice must not be negative. if invoice.Value < 0 { - return nil, fmt.Errorf("payments of negative value "+ + return nil, nil, fmt.Errorf("payments of negative value "+ "are not allowed, value is %v", invoice.Value) } - amt := btcutil.Amount(invoice.Value) - amtMSat := lnwire.NewMSatFromSatoshis(amt) + amtMSat := lnwire.NewMSatFromSatoshis(invoice.Value) // The value of the invoice must also not exceed the current soft-limit // on the largest payment within the network. if amtMSat > cfg.MaxPaymentMSat { - return nil, fmt.Errorf("payment of %v is too large, max "+ - "payment allowed is %v", amt, + return nil, nil, fmt.Errorf("payment of %v is too large, max "+ + "payment allowed is %v", invoice.Value, cfg.MaxPaymentMSat.ToSatoshis(), ) } // Next, generate the payment hash itself from the preimage. This will // be used by clients to query for the state of a particular invoice. - rHash := sha256.Sum256(paymentPreimage[:]) + rHash := paymentPreimage.Hash() // We also create an encoded payment request which allows the // caller to compactly send the invoice to the payer. We'll create a @@ -134,7 +157,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, addr, err := btcutil.DecodeAddress(invoice.FallbackAddr, cfg.ChainParams) if err != nil { - return nil, fmt.Errorf("invalid fallback address: %v", + return nil, nil, fmt.Errorf("invalid fallback address: %v", err) } options = append(options, zpay32.FallbackAddr(addr)) @@ -152,7 +175,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, expSeconds := invoice.Expiry if float64(expSeconds) > maxExpiry.Seconds() { - return nil, fmt.Errorf("expiry of %v seconds "+ + return nil, nil, fmt.Errorf("expiry of %v seconds "+ "greater than max expiry of %v seconds", float64(expSeconds), maxExpiry.Seconds()) } @@ -177,7 +200,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, // an option on the command line when creating an invoice. switch { case invoice.CltvExpiry > math.MaxUint16: - return nil, fmt.Errorf("CLTV delta of %v is too large, max "+ + return nil, nil, fmt.Errorf("CLTV delta of %v is too large, max "+ "accepted is: %v", invoice.CltvExpiry, math.MaxUint16) case invoice.CltvExpiry != 0: options = append(options, @@ -194,7 +217,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, if invoice.Private { openChannels, err := cfg.ChanDB.FetchAllChannels() if err != nil { - return nil, fmt.Errorf("could not fetch all channels") + return nil, nil, fmt.Errorf("could not fetch all channels") } graph := cfg.ChanDB.ChannelGraph() @@ -312,7 +335,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, cfg.ChainParams, rHash, creationDate, options..., ) if err != nil { - return nil, err + return nil, nil, err } payReqString, err := payReq.Encode( @@ -321,7 +344,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, }, ) if err != nil { - return nil, err + return nil, nil, err } newInvoice := &channeldb.Invoice{ @@ -342,14 +365,10 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, ) // With all sanity checks passed, write the invoice to the database. - addIndex, err := cfg.AddInvoice(newInvoice, rHash) + _, err = cfg.AddInvoice(newInvoice, rHash) if err != nil { - return nil, err + return nil, nil, err } - return &lnrpc.AddInvoiceResponse{ - RHash: rHash[:], - PaymentRequest: payReqString, - AddIndex: addIndex, - }, nil + return &rHash, newInvoice, nil } diff --git a/rpcserver.go b/rpcserver.go index ff251492..cccc498b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -38,6 +38,7 @@ import ( "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/macaroons" @@ -3291,7 +3292,37 @@ func (r *rpcServer) AddInvoice(ctx context.Context, ChanDB: r.server.chanDB, } - return invoicesrpc.AddInvoice(ctx, addInvoiceCfg, invoice) + addInvoiceData := &invoicesrpc.AddInvoiceData{ + Memo: invoice.Memo, + Receipt: invoice.Receipt, + Value: btcutil.Amount(invoice.Value), + DescriptionHash: invoice.DescriptionHash, + Expiry: invoice.Expiry, + FallbackAddr: invoice.FallbackAddr, + CltvExpiry: invoice.CltvExpiry, + Private: invoice.Private, + } + + if invoice.RPreimage != nil { + preimage, err := lntypes.MakePreimage(invoice.RPreimage) + if err != nil { + return nil, err + } + addInvoiceData.Preimage = &preimage + } + + hash, dbInvoice, err := invoicesrpc.AddInvoice( + ctx, addInvoiceCfg, addInvoiceData, + ) + if err != nil { + return nil, err + } + + return &lnrpc.AddInvoiceResponse{ + AddIndex: dbInvoice.AddIndex, + PaymentRequest: string(dbInvoice.PaymentRequest), + RHash: hash[:], + }, nil } // LookupInvoice attempts to look up an invoice according to its payment hash.