mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-26 08:55:59 +01:00
zpay32: add payment metadata field
This commit is contained in:
parent
044286ae2c
commit
135e27ddd3
4 changed files with 75 additions and 5 deletions
|
@ -229,6 +229,15 @@ func parseTaggedFields(invoice *Invoice, fields []byte, net *chaincfg.Params) er
|
|||
}
|
||||
|
||||
invoice.Description, err = parseDescription(base32Data)
|
||||
case fieldTypeM:
|
||||
if invoice.Metadata != nil {
|
||||
// We skip the field if we have already seen a
|
||||
// supported one.
|
||||
continue
|
||||
}
|
||||
|
||||
invoice.Metadata, err = parseMetadata(base32Data)
|
||||
|
||||
case fieldTypeN:
|
||||
if invoice.Destination != nil {
|
||||
// We skip the field if we have already seen a
|
||||
|
@ -345,6 +354,12 @@ func parseDescription(data []byte) (*string, error) {
|
|||
return &description, nil
|
||||
}
|
||||
|
||||
// parseMetadata converts the data (encoded in base32) into a byte slice to use
|
||||
// as the metadata.
|
||||
func parseMetadata(data []byte) ([]byte, error) {
|
||||
return bech32.ConvertBits(data, 5, 8, false)
|
||||
}
|
||||
|
||||
// parseDestination converts the data (encoded in base32) into a 33-byte public
|
||||
// key of the payee node.
|
||||
func parseDestination(data []byte) (*btcec.PublicKey, error) {
|
||||
|
|
|
@ -164,6 +164,17 @@ func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
|
|||
}
|
||||
}
|
||||
|
||||
if invoice.Metadata != nil {
|
||||
base32, err := bech32.ConvertBits(invoice.Metadata, 8, 5, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = writeTaggedField(bufferBase32, fieldTypeM, base32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if invoice.minFinalCLTVExpiry != nil {
|
||||
finalDelta := uint64ToBase32(*invoice.minFinalCLTVExpiry)
|
||||
err := writeTaggedField(bufferBase32, fieldTypeC, finalDelta)
|
||||
|
|
|
@ -46,6 +46,9 @@ const (
|
|||
// fieldTypeD contains a short description of the payment.
|
||||
fieldTypeD = 13
|
||||
|
||||
// fieldTypeM contains the payment metadata.
|
||||
fieldTypeM = 27
|
||||
|
||||
// fieldTypeN contains the pubkey of the target node.
|
||||
fieldTypeN = 19
|
||||
|
||||
|
@ -183,6 +186,10 @@ type Invoice struct {
|
|||
// Features represents an optional field used to signal optional or
|
||||
// required support for features by the receiver.
|
||||
Features *lnwire.FeatureVector
|
||||
|
||||
// Metadata is additional data that is sent along with the payment to
|
||||
// the payee.
|
||||
Metadata []byte
|
||||
}
|
||||
|
||||
// Amount is a functional option that allows callers of NewInvoice to set the
|
||||
|
@ -273,6 +280,14 @@ func PaymentAddr(addr [32]byte) func(*Invoice) {
|
|||
}
|
||||
}
|
||||
|
||||
// Metadata is a functional option that allows callers of NewInvoice to set
|
||||
// the desired payment Metadata tht is advertised on the invoice.
|
||||
func Metadata(metadata []byte) func(*Invoice) {
|
||||
return func(i *Invoice) {
|
||||
i.Metadata = metadata
|
||||
}
|
||||
}
|
||||
|
||||
// NewInvoice creates a new Invoice object. The last parameter is a set of
|
||||
// variadic arguments for setting optional fields of the invoice.
|
||||
//
|
||||
|
|
|
@ -27,6 +27,7 @@ var (
|
|||
testMillisat2500uBTC = lnwire.MilliSatoshi(250000000)
|
||||
testMillisat25mBTC = lnwire.MilliSatoshi(2500000000)
|
||||
testMillisat20mBTC = lnwire.MilliSatoshi(2000000000)
|
||||
testMillisat10mBTC = lnwire.MilliSatoshi(1000000000)
|
||||
|
||||
testPaymentHash = [32]byte{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
|
@ -49,11 +50,12 @@ var (
|
|||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
}
|
||||
|
||||
testEmptyString = ""
|
||||
testCupOfCoffee = "1 cup coffee"
|
||||
testCoffeeBeans = "coffee beans"
|
||||
testCupOfNonsense = "ナンセンス 1杯"
|
||||
testPleaseConsider = "Please consider supporting this project"
|
||||
testEmptyString = ""
|
||||
testCupOfCoffee = "1 cup coffee"
|
||||
testCoffeeBeans = "coffee beans"
|
||||
testCupOfNonsense = "ナンセンス 1杯"
|
||||
testPleaseConsider = "Please consider supporting this project"
|
||||
testPaymentMetadata = "payment metadata inside"
|
||||
|
||||
testPrivKeyBytes, _ = hex.DecodeString("e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734")
|
||||
testPrivKey, testPubKey = btcec.PrivKeyFromBytes(testPrivKeyBytes)
|
||||
|
@ -692,6 +694,33 @@ func TestDecodeEncode(t *testing.T) {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// Please send 0.01 BTC with payment metadata 0x01fafaf0.
|
||||
encodedInvoice: "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc",
|
||||
valid: true,
|
||||
decodedInvoice: func() *Invoice {
|
||||
return &Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat10mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
PaymentHash: &testPaymentHash,
|
||||
Description: &testPaymentMetadata,
|
||||
Destination: testPubKey,
|
||||
PaymentAddr: &specPaymentAddr,
|
||||
Features: lnwire.NewFeatureVector(
|
||||
lnwire.NewRawFeatureVector(8, 14, 48),
|
||||
lnwire.Features,
|
||||
),
|
||||
Metadata: []byte{0x01, 0xfa, 0xfa, 0xf0},
|
||||
}
|
||||
},
|
||||
beforeEncoding: func(i *Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
i.Destination = nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
|
|
Loading…
Add table
Reference in a new issue