mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-26 01:33:02 +01:00
zpay32: move the BOLT-11 compatible invoice format to zpay32 namespace
This commit is contained in:
parent
9d31b6c4fd
commit
b645f02418
@ -1,4 +1,4 @@
|
||||
package invoice
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package invoice
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package invoice
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -1,4 +1,4 @@
|
||||
package invoice
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,4 +1,4 @@
|
||||
package invoice_test
|
||||
package zpay32_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -8,8 +8,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/invoice"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
"github.com/roasbeef/btcd/chaincfg"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
@ -45,7 +45,7 @@ var (
|
||||
testPaymentHash [32]byte
|
||||
testDescriptionHash [32]byte
|
||||
|
||||
testMessageSigner = invoice.MessageSigner{
|
||||
testMessageSigner = zpay32.MessageSigner{
|
||||
SignCompact: func(hash []byte) ([]byte, error) {
|
||||
sig, err := btcec.SignCompact(btcec.S256(),
|
||||
testPrivKey, hash, true)
|
||||
@ -72,9 +72,9 @@ func TestDecodeEncode(t *testing.T) {
|
||||
tests := []struct {
|
||||
encodedInvoice string
|
||||
valid bool
|
||||
decodedInvoice *invoice.Invoice
|
||||
decodedInvoice *zpay32.Invoice
|
||||
skipEncoding bool
|
||||
beforeEncoding func(*invoice.Invoice)
|
||||
beforeEncoding func(*zpay32.Invoice)
|
||||
}{
|
||||
{
|
||||
encodedInvoice: "asdsaddnasdnas", // no hrp
|
||||
@ -112,7 +112,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// no payment hash set
|
||||
encodedInvoice: "lnbc20m1pvjluezhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsjv38luh6p6s2xrv3mzvlmzaya43376h0twal5ax0k6p47498hp3hnaymzhsn424rxqjs0q7apn26yrhaxltq3vzwpqj9nc2r3kzwccsplnq470",
|
||||
valid: false,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -124,7 +124,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Both Description and DescriptionHash set.
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs03vghs8y0kuj4ulrzls8ln7fnm9dk7sjsnqmghql6hd6jut36clkqpyuq0s5m6fhureyz0szx2qjc8hkgf4xc2hpw8jpu26jfeyvf4cpga36gt",
|
||||
valid: false,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -138,7 +138,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Neither Description nor DescriptionHash set.
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqn2rne0kagfl4e0xag0w6hqeg2dwgc54hrm9m0auw52dhwhwcu559qav309h598pyzn69wh2nqauneyyesnpmaax0g6acr8lh9559jmcquyq5a9",
|
||||
valid: false,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -150,7 +150,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Has a few unknown fields, should just be ignored.
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaqtq2v93xxer9vczq8v93xxeqv72xr42ca60022jqu6fu73n453tmnr0ukc0pl0t23w7eavtensjz0j2wcu7nkxhfdgp9y37welajh5kw34mq7m4xuay0a72cwec8qwgqt5vqht",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -164,7 +164,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Ignore unknown witness version in fallback address.
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpppw508d6qejxtdg4y5r3zarvary0c5xw7k8txqv6x0a75xuzp0zsdzk5hq6tmfgweltvs6jk5nhtyd9uqksvr48zga9mw08667w8264gkspluu66jhtcmct36nx363km6cquhhv2cpc6q43r",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -178,7 +178,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Ignore fields with unknown lengths.
|
||||
encodedInvoice: "lnbc241pveeq09pp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqpp3qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqshp38yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66np3q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfy8huflvs2zwkymx47cszugvzn5v64ahemzzlmm62rpn9l9rm05h35aceq00tkt296289wepws9jh4499wq2l0vk6xcxffd90dpuqchqqztyayq",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat24BTC,
|
||||
Timestamp: time.Unix(1503429093, 0),
|
||||
@ -192,14 +192,14 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Please make a donation of any amount using rhash 0001020304050607080900010203040506070809000102030405060708090102 to me @03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad
|
||||
encodedInvoice: "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
PaymentHash: &testPaymentHash,
|
||||
Description: &testPleaseConsider,
|
||||
Destination: testPubKey,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -210,7 +210,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Same as above, pubkey set in 'n' field.
|
||||
encodedInvoice: "lnbc241pveeq09pp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdqqnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66jd3m5klcwhq68vdsmx2rjgxeay5v0tkt2v5sjaky4eqahe4fx3k9sqavvce3capfuwv8rvjng57jrtfajn5dkpqv8yelsewtljwmmycq62k443",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat24BTC,
|
||||
Timestamp: time.Unix(1503429093, 0),
|
||||
@ -223,7 +223,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Please send $3 for a cup of coffee to the same peer, within 1 minute
|
||||
encodedInvoice: "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspfj9srp",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat2500uBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -232,7 +232,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
Destination: testPubKey,
|
||||
Expiry: &testExpiry60,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -243,7 +243,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// Now send $24 for an entire list of things (hashed)
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqscc6gd6ql3jrc5yzme8v4ntcewwz5cnw92tz0pc8qcuufvq7khhr8wpald05e92xw006sq94mg8v2ndf4sefvf9sygkshp5zfem29trqq2yxxz7",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -251,7 +251,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
DescriptionHash: &testDescriptionHash,
|
||||
Destination: testPubKey,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -262,7 +262,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// The same, on testnet, with a fallback address mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP
|
||||
encodedInvoice: "lntb20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3x9et2e20v6pu37c5d9vax37wxq72un98k6vcx9fz94w0qf237cm2rqv9pmn5lnexfvf5579slr4zq3u8kmczecytdx0xg9rwzngp7e6guwqpqlhssu04sucpnz4axcv2dstmknqq6jsk2l",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.TestNet3Params,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -271,7 +271,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testAddrTestnet,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -282,7 +282,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// On mainnet, with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to get to node 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85frzjq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvncsk57n4v9ehw86wq8fzvjejhv9z3w3q5zh6qkql005x9xl240ch23jk79ujzvr4hsmmafyxghpqe79psktnjl668ntaf4ne7ucs5csqh5mnnk",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -290,7 +290,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
DescriptionHash: &testDescriptionHash,
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testRustyAddr,
|
||||
RoutingInfo: []invoice.ExtraRoutingInfo{
|
||||
RoutingInfo: []zpay32.ExtraRoutingInfo{
|
||||
{
|
||||
PubKey: testRoutingInfoPubkey,
|
||||
ShortChanID: 0x0102030405060708,
|
||||
@ -299,7 +299,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -310,7 +310,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// On mainnet, with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to go via nodes 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255 then 039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqqqqqqq7qqzqfnlkwydm8rg30gjku7wmxmk06sevjp53fmvrcfegvwy7d5443jvyhxsel0hulkstws7vqv400q4j3wgpk4crg49682hr4scqvmad43cqd5m7tf",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -318,7 +318,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
DescriptionHash: &testDescriptionHash,
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testRustyAddr,
|
||||
RoutingInfo: []invoice.ExtraRoutingInfo{
|
||||
RoutingInfo: []zpay32.ExtraRoutingInfo{
|
||||
{
|
||||
PubKey: testRoutingInfoPubkey,
|
||||
ShortChanID: 0x0102030405060708,
|
||||
@ -333,7 +333,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -344,7 +344,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// On mainnet, with fallback (p2sh) address 3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfppj3a24vwu6r8ejrss3axul8rxldph2q7z9kk822r8plup77n9yq5ep2dfpcydrjwzxs0la84v3tfw43t3vqhek7f05m6uf8lmfkjn7zv7enn76sq65d8u9lxav2pl6x3xnc2ww3lqpagnh0u",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -353,7 +353,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testAddrMainnetP2SH,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -364,7 +364,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// On mainnet, with fallback (p2wpkh) address bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfppqw508d6qejxtdg4y5r3zarvary0c5xw7kknt6zz5vxa8yh8jrnlkl63dah48yh6eupakk87fjdcnwqfcyt7snnpuz7vp83txauq4c60sys3xyucesxjf46yqnpplj0saq36a554cp9wt865",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -373,7 +373,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testAddrMainnetP2WPKH,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -384,7 +384,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
// On mainnet, with fallback (p2wsh) address bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3
|
||||
encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qvnjha2auylmwrltv2pkp2t22uy8ura2xsdwhq5nm7s574xva47djmnj2xeycsu7u5v8929mvuux43j0cqhhf32wfyn2th0sv4t9x55sppz5we8",
|
||||
valid: true,
|
||||
decodedInvoice: &invoice.Invoice{
|
||||
decodedInvoice: &zpay32.Invoice{
|
||||
Net: &chaincfg.MainNetParams,
|
||||
MilliSat: &testMillisat20mBTC,
|
||||
Timestamp: time.Unix(1496314658, 0),
|
||||
@ -393,7 +393,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testAddrMainnetP2WSH,
|
||||
},
|
||||
beforeEncoding: func(i *invoice.Invoice) {
|
||||
beforeEncoding: func(i *zpay32.Invoice) {
|
||||
// Since this destination pubkey was recovered
|
||||
// from the signature, we must set it nil before
|
||||
// encoding to get back the same invoice string.
|
||||
@ -403,7 +403,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
invoice, err := invoice.Decode(test.encodedInvoice)
|
||||
invoice, err := zpay32.Decode(test.encodedInvoice)
|
||||
if (err == nil) != test.valid {
|
||||
t.Errorf("Decoding test %d failed: %v", i, err)
|
||||
return
|
||||
@ -448,42 +448,42 @@ func TestNewInvoice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
newInvoice func() (*invoice.Invoice, error)
|
||||
newInvoice func() (*zpay32.Invoice, error)
|
||||
encodedInvoice string
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
// Both Description and DescriptionHash set.
|
||||
newInvoice: func() (*invoice.Invoice, error) {
|
||||
return invoice.NewInvoice(&chaincfg.MainNetParams,
|
||||
newInvoice: func() (*zpay32.Invoice, error) {
|
||||
return zpay32.NewInvoice(&chaincfg.MainNetParams,
|
||||
testPaymentHash, time.Unix(1496314658, 0),
|
||||
invoice.DescriptionHash(testDescriptionHash),
|
||||
invoice.Description(testPleaseConsider))
|
||||
zpay32.DescriptionHash(testDescriptionHash),
|
||||
zpay32.Description(testPleaseConsider))
|
||||
},
|
||||
valid: false, // Both Description and DescriptionHash set.
|
||||
},
|
||||
{
|
||||
// 'n' field set.
|
||||
newInvoice: func() (*invoice.Invoice, error) {
|
||||
return invoice.NewInvoice(&chaincfg.MainNetParams,
|
||||
newInvoice: func() (*zpay32.Invoice, error) {
|
||||
return zpay32.NewInvoice(&chaincfg.MainNetParams,
|
||||
testPaymentHash, time.Unix(1503429093, 0),
|
||||
invoice.Amount(testMillisat24BTC),
|
||||
invoice.Description(testEmptyString),
|
||||
invoice.Destination(testPubKey))
|
||||
zpay32.Amount(testMillisat24BTC),
|
||||
zpay32.Description(testEmptyString),
|
||||
zpay32.Destination(testPubKey))
|
||||
},
|
||||
valid: true,
|
||||
encodedInvoice: "lnbc241pveeq09pp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdqqnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66jd3m5klcwhq68vdsmx2rjgxeay5v0tkt2v5sjaky4eqahe4fx3k9sqavvce3capfuwv8rvjng57jrtfajn5dkpqv8yelsewtljwmmycq62k443",
|
||||
},
|
||||
{
|
||||
// On mainnet, with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to go via nodes 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255 then 039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255
|
||||
newInvoice: func() (*invoice.Invoice, error) {
|
||||
return invoice.NewInvoice(&chaincfg.MainNetParams,
|
||||
newInvoice: func() (*zpay32.Invoice, error) {
|
||||
return zpay32.NewInvoice(&chaincfg.MainNetParams,
|
||||
testPaymentHash, time.Unix(1496314658, 0),
|
||||
invoice.Amount(testMillisat20mBTC),
|
||||
invoice.DescriptionHash(testDescriptionHash),
|
||||
invoice.FallbackAddr(testRustyAddr),
|
||||
invoice.RoutingInfo(
|
||||
[]invoice.ExtraRoutingInfo{
|
||||
zpay32.Amount(testMillisat20mBTC),
|
||||
zpay32.DescriptionHash(testDescriptionHash),
|
||||
zpay32.FallbackAddr(testRustyAddr),
|
||||
zpay32.RoutingInfo(
|
||||
[]zpay32.ExtraRoutingInfo{
|
||||
{
|
||||
PubKey: testRoutingInfoPubkey,
|
||||
ShortChanID: 0x0102030405060708,
|
||||
@ -525,7 +525,7 @@ func TestNewInvoice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func compareInvoices(expected, actual *invoice.Invoice) error {
|
||||
func compareInvoices(expected, actual *zpay32.Invoice) error {
|
||||
if !reflect.DeepEqual(expected.Net, actual.Net) {
|
||||
return fmt.Errorf("expected net %v, got %v",
|
||||
expected.Net, actual.Net)
|
@ -1,150 +0,0 @@
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
"github.com/roasbeef/btcutil"
|
||||
"github.com/tv42/zbase32"
|
||||
)
|
||||
|
||||
// invoiceSize is the size of an encoded invoice without the added check-sum.
|
||||
// The size of broken down as follows: 33-bytes (destination pub key), 32-bytes
|
||||
// (payment hash), 8-bytes for the payment amount in satoshis.
|
||||
const invoiceSize = 33 + 32 + 8
|
||||
|
||||
// ErrCheckSumMismatch is returned byt he Decode function fi when
|
||||
// decoding an encoded invoice, the checksum doesn't match indicating
|
||||
// an error somewhere in the bitstream.
|
||||
var ErrCheckSumMismatch = errors.New("the checksum is incorrect")
|
||||
|
||||
// ErrDataTooShort is returned by the Decode function if when
|
||||
// decoding an encoded payment request, the number of bytes decoded
|
||||
// is too few for a valid invoice indicating invalid input.
|
||||
var ErrDataTooShort = errors.New("the decoded data is too short")
|
||||
|
||||
// PaymentRequest is a bare-bones invoice for a payment within the Lightning
|
||||
// Network. With the details of the invoice, the sender has all the data
|
||||
// necessary to send a payment to the recipient.
|
||||
type PaymentRequest struct {
|
||||
// Destination is the public key of the node to be paid.
|
||||
Destination *btcec.PublicKey
|
||||
|
||||
// PaymentHash is the has to use within the HTLC extended throughout
|
||||
// the payment path to the destination.
|
||||
PaymentHash [32]byte
|
||||
|
||||
// Amount is the amount to be sent to the destination expressed in
|
||||
// satoshis.
|
||||
Amount btcutil.Amount
|
||||
}
|
||||
|
||||
// castagnoli is an initialized crc32 checksum generated which Castagnoli's
|
||||
// polynomial.
|
||||
var castagnoli = crc32.MakeTable(crc32.Castagnoli)
|
||||
|
||||
// checkSum calculates a 4-byte crc32 checksum of the passed data. The returned
|
||||
// uint32 is serialized as a big-endian integer.
|
||||
func checkSum(data []byte) []byte {
|
||||
crc := crc32.New(castagnoli)
|
||||
crc.Write(data)
|
||||
return crc.Sum(nil)
|
||||
}
|
||||
|
||||
// Encode encodes the passed payment request using zbase32 with an added 4-byte
|
||||
// crc32 checksum. The resulting encoding is 77-bytes long and consists of 124
|
||||
// ASCII characters.
|
||||
// TODO(roasbeef): add version byte?
|
||||
func Encode(payReq *PaymentRequest) string {
|
||||
var (
|
||||
invoiceBytes [invoiceSize]byte
|
||||
n int
|
||||
)
|
||||
|
||||
// First copy each of the elements of the payment request into the
|
||||
// buffer. Creating a stream that resembles: dest || r_hash || amt
|
||||
n += copy(invoiceBytes[:], payReq.Destination.SerializeCompressed())
|
||||
n += copy(invoiceBytes[n:], payReq.PaymentHash[:])
|
||||
binary.BigEndian.PutUint64(invoiceBytes[n:], uint64(payReq.Amount))
|
||||
|
||||
// Next, we append the checksum to the end of the buffer which covers
|
||||
// the serialized payment request.
|
||||
b := append(invoiceBytes[:], checkSum(invoiceBytes[:])...)
|
||||
|
||||
// Finally encode the raw bytes as a zbase32 encoded string.
|
||||
return zbase32.EncodeToString(b)
|
||||
}
|
||||
|
||||
// Decode attempts to decode the zbase32 encoded payment request. If the
|
||||
// trailing checksum doesn't match, then an error is returned.
|
||||
func Decode(payData string) (*PaymentRequest, error) {
|
||||
if payData == "" {
|
||||
return nil, fmt.Errorf("encoded payment request must be a " +
|
||||
"non-empty string")
|
||||
}
|
||||
|
||||
// First we decode the zbase32 encoded string into a series of raw
|
||||
// bytes.
|
||||
payReqBytes, err := zbase32.DecodeString(payData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if there are at least enough bytes to represent the invoice
|
||||
// and the checksum.
|
||||
if len(payReqBytes) < invoiceSize+crc32.Size {
|
||||
return nil, ErrDataTooShort
|
||||
}
|
||||
|
||||
// With the bytes decoded, we verify the checksum to ensure the
|
||||
// payment request wasn't altered in its decoded form.
|
||||
invoiceBytes := payReqBytes[:invoiceSize]
|
||||
generatedSum := checkSum(invoiceBytes)
|
||||
|
||||
// If the checksums don't match, then we return an error to the
|
||||
// possibly detected error.
|
||||
encodedSum := payReqBytes[invoiceSize:]
|
||||
if !bytes.Equal(encodedSum, generatedSum) {
|
||||
return nil, ErrCheckSumMismatch
|
||||
}
|
||||
|
||||
// Otherwise, we've verified the integrity of the encoded payment
|
||||
// request and can safely decode the payReq, passing it back up to the
|
||||
// caller.
|
||||
invoiceReader := bytes.NewReader(invoiceBytes)
|
||||
return decodePaymentRequest(invoiceReader)
|
||||
}
|
||||
|
||||
func decodePaymentRequest(r io.Reader) (*PaymentRequest, error) {
|
||||
var err error
|
||||
|
||||
i := &PaymentRequest{}
|
||||
|
||||
var pubKey [33]byte
|
||||
if _, err := io.ReadFull(r, pubKey[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.Destination, err = btcec.ParsePubKey(pubKey[:], btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(r, i.PaymentHash[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var amt [8]byte
|
||||
if _, err := io.ReadFull(r, amt[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.Amount = btcutil.Amount(binary.BigEndian.Uint64(amt[:]))
|
||||
|
||||
return i, nil
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
"github.com/roasbeef/btcutil"
|
||||
)
|
||||
|
||||
var (
|
||||
testPrivKey = []byte{
|
||||
0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
|
||||
0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
|
||||
0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
|
||||
0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
|
||||
}
|
||||
|
||||
_, testPubKey = btcec.PrivKeyFromBytes(btcec.S256(), testPrivKey)
|
||||
|
||||
testPayHash = [32]byte{
|
||||
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
||||
0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
|
||||
0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
|
||||
0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
|
||||
}
|
||||
)
|
||||
|
||||
func TestEncodeDecode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testPubKey.Curve = nil
|
||||
tests := []struct {
|
||||
version int
|
||||
payReq PaymentRequest
|
||||
encoding string
|
||||
}{
|
||||
{
|
||||
payReq: PaymentRequest{
|
||||
Destination: testPubKey,
|
||||
PaymentHash: testPayHash,
|
||||
Amount: btcutil.Amount(50000),
|
||||
},
|
||||
encoding: "yj8p9uh793syszrd4giu66gtsqprp47cc6cqbdo3" +
|
||||
"qaxi7sr63y6bbphw8bx148zzipg3rh6t1btadpnxf7z1mnfd76" +
|
||||
"hsw1eaoca3ot4uyyyyyyyyydbib998je6o",
|
||||
version: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
// First ensure encoding the test payment request string in the
|
||||
// specified encoding.
|
||||
encodedReq := Encode(&test.payReq)
|
||||
if encodedReq != test.encoding {
|
||||
t.Fatalf("encoding mismatch for %v: expected %v got %v",
|
||||
spew.Sdump(test.payReq), test.encoding, encodedReq)
|
||||
}
|
||||
|
||||
// Next ensure the correctness of the transformation in the
|
||||
// other direction.
|
||||
decodedReq, err := Decode(test.encoding)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decode invoice #%v: %v", i, err)
|
||||
}
|
||||
|
||||
if !test.payReq.Destination.IsEqual(decodedReq.Destination) {
|
||||
t.Fatalf("test #%v:, destination mismatch for decoded request: "+
|
||||
"expected %v got %v", i, test.payReq.Destination,
|
||||
decodedReq.Destination)
|
||||
}
|
||||
if !bytes.Equal(test.payReq.PaymentHash[:], decodedReq.PaymentHash[:]) {
|
||||
t.Fatalf("test #%v: payment hash mismatch for decoded request: "+
|
||||
"expected %x got %x", i, test.payReq.PaymentHash,
|
||||
decodedReq.PaymentHash)
|
||||
}
|
||||
if test.payReq.Amount != decodedReq.Amount {
|
||||
t.Fatalf("test #%v: amount mismatch for decoded request: "+
|
||||
"expected %x got %x", i, test.payReq.Amount,
|
||||
decodedReq.Amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestChecksumMismatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We start with a pre-encoded invoice, which has a valid checksum.
|
||||
payReqString := []byte("ycyr8brdjic6oak3bemztc5nupo56y3itq4z5q4qxwb35orf7fmj5phw8bx148zzipg3rh6t1btadpnxf7z1mnfd76hsw1eaoca3ot4uyyyyyyyyydbibt79jo1o")
|
||||
|
||||
// To modify the resulting checksum, we shift a few of the bytes within the
|
||||
// string itself.
|
||||
payReqString[1] = 98
|
||||
payReqString[5] = 102
|
||||
|
||||
if _, err := Decode(string(payReqString)); err != ErrCheckSumMismatch {
|
||||
t.Fatalf("decode should fail with checksum mismatch, instead: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeTooShort(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We start with a pre-encoded too-short string.
|
||||
payReqString := "ycyr8brdji"
|
||||
|
||||
if _, err := Decode(payReqString); err != ErrDataTooShort {
|
||||
t.Fatalf("decode should fail with data too short, instead: %v", err)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user