diff --git a/zpay32/invoice_internal_test.go b/zpay32/invoice_internal_test.go index 0a41b4c4d..22434a99b 100644 --- a/zpay32/invoice_internal_test.go +++ b/zpay32/invoice_internal_test.go @@ -593,19 +593,34 @@ func TestParseFallbackAddr(t *testing.T) { t.Parallel() testAddrTestnetData, _ := bech32.ConvertBits(testAddrTestnet.ScriptAddress(), 8, 5, true) - testAddrTestnetDataWithVersion := append([]byte{17}, testAddrTestnetData...) + testAddrTestnetDataWithVersion := append( + []byte{fallbackVersionPubkeyHash}, testAddrTestnetData..., + ) testRustyAddrData, _ := bech32.ConvertBits(testRustyAddr.ScriptAddress(), 8, 5, true) - testRustyAddrDataWithVersion := append([]byte{17}, testRustyAddrData...) + testRustyAddrDataWithVersion := append( + []byte{fallbackVersionPubkeyHash}, testRustyAddrData..., + ) testAddrMainnetP2SHData, _ := bech32.ConvertBits(testAddrMainnetP2SH.ScriptAddress(), 8, 5, true) - testAddrMainnetP2SHDataWithVersion := append([]byte{18}, testAddrMainnetP2SHData...) + testAddrMainnetP2SHDataWithVersion := append( + []byte{fallbackVersionScriptHash}, testAddrMainnetP2SHData..., + ) testAddrMainnetP2WPKHData, _ := bech32.ConvertBits(testAddrMainnetP2WPKH.ScriptAddress(), 8, 5, true) - testAddrMainnetP2WPKHDataWithVersion := append([]byte{0}, testAddrMainnetP2WPKHData...) + testAddrMainnetP2WPKHDataWithVersion := append( + []byte{fallbackVersionWitness}, testAddrMainnetP2WPKHData..., + ) testAddrMainnetP2WSHData, _ := bech32.ConvertBits(testAddrMainnetP2WSH.ScriptAddress(), 8, 5, true) - testAddrMainnetP2WSHDataWithVersion := append([]byte{0}, testAddrMainnetP2WSHData...) + testAddrMainnetP2WSHDataWithVersion := append( + []byte{fallbackVersionWitness}, testAddrMainnetP2WSHData..., + ) + + testAddrMainnetP2TRData, _ := bech32.ConvertBits( + testAddrMainnetP2TR.ScriptAddress(), 8, 5, true) + testAddrMainnetP2TRDataWithVersion := append( + []byte{fallbackVersionTaproot}, testAddrMainnetP2TRData...) tests := []struct { data []byte @@ -651,6 +666,17 @@ func TestParseFallbackAddr(t *testing.T) { valid: true, result: testAddrMainnetP2WSH, }, + { + data: testAddrMainnetP2TRDataWithVersion, + net: &chaincfg.MainNetParams, + valid: true, + result: testAddrMainnetP2TR, + }, + { + data: testAddrMainnetP2TRDataWithVersion[:10], + net: &chaincfg.MainNetParams, + valid: false, // data too short for P2TR address + }, } for i, test := range tests { diff --git a/zpay32/invoice_test.go b/zpay32/invoice_test.go index 4cb1a6170..bfa1539f3 100644 --- a/zpay32/invoice_test.go +++ b/zpay32/invoice_test.go @@ -71,6 +71,9 @@ var ( testAddrMainnetP2SH, _ = btcutil.DecodeAddress("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX", &chaincfg.MainNetParams) testAddrMainnetP2WPKH, _ = btcutil.DecodeAddress("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", &chaincfg.MainNetParams) testAddrMainnetP2WSH, _ = btcutil.DecodeAddress("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", &chaincfg.MainNetParams) + testAddrMainnetP2TR, _ = btcutil.DecodeAddress("bc1pptdvg0d2nj99568"+ + "qn6ssdy4cygnwuxgw2ukmnwgwz7jpqjz2kszse2s3lm", + &chaincfg.MainNetParams) testHopHintPubkeyBytes1, _ = hex.DecodeString("029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255") testHopHintPubkey1, _ = btcec.ParsePubKey(testHopHintPubkeyBytes1) @@ -299,8 +302,14 @@ func TestDecodeEncode(t *testing.T) { }, { // Ignore unknown witness version in fallback address. - encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpppw508d6qejxtdg4y5r3zarvary0c5xw7k8txqv6x0a75xuzp0zsdzk5hq6tmfgweltvs6jk5nhtyd9uqksvr48zga9mw08667w8264gkspluu66jhtcmct36nx363km6cquhhv2cpc6q43r", - valid: true, + encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqq" + + "qsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan" + + "79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrq" + + "sfp4z6yn92zrp97a6q5hhh8swys7uf4hm9tr8a0xylnk" + + "26fvkg3jx0sdsxvma0zvf2h0pycyyzdrmjncq6lzrfuw" + + "xfhv6gzz4q5303n3up6as4ghe5qthg7x20z7vae8w5rq" + + "u6de3g4jl7kvuap3qedprqsqqmgqqm6s8sl", + valid: true, decodedInvoice: func() *Invoice { return &Invoice{ Net: &chaincfg.MainNetParams, @@ -649,6 +658,74 @@ func TestDecodeEncode(t *testing.T) { i.Destination = nil }, }, + { + // On mainnet, with fallback (p2tr) address "bc1pptdvg0d + // 2nj99568qn6ssdy4cygnwuxgw2ukmnwgwz7jpqjz2kszse2s3lm" + encodedInvoice: "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqq" + + "qsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan" + + "79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrq" + + "sfp4pptdvg0d2nj99568qn6ssdy4cygnwuxgw2ukmnwg" + + "wz7jpqjz2kszs9zs3tmcpgulwc0ruwc2cm97udy6sdfe" + + "nwvha8qlkfwx49sgk40kze4kwsh706rae3uc30ltpwpw" + + "mjyhc3uan4ljz56wksg5gsnhrrhcqsrq93d", + + valid: true, + decodedInvoice: func() *Invoice { + return &Invoice{ + Net: &chaincfg.MainNetParams, + MilliSat: &testMillisat20mBTC, + Timestamp: time.Unix(1496314658, 0), + PaymentHash: &testPaymentHash, + DescriptionHash: &testDescriptionHash, + Destination: testPubKey, + FallbackAddr: testAddrMainnetP2TR, + Features: emptyFeatures, + } + }, + 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 + }, + }, + { + // On mainnet, with fallback (p2tr) address "bc1pptdvg0d + // 2nj99568qn6ssdy4cygnwuxgw2ukmnwgwz7jpqjz2kszse2s3lm" + // using the test vector payment from BOLT 11 + encodedInvoice: "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zy" + + "g3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqc" + + "yq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqyp" + + "qhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98kly" + + "sy043l2ahrqsfp4pptdvg0d2nj99568qn6ssdy4cygnw" + + "uxgw2ukmnwgwz7jpqjz2kszs9qrsgqy606dznq28exny" + + "dt2r4c29y56xjtn3sk4mhgjtl4pg2y4ar3249rq4ajlm" + + "j9jy8zvlzw7cr8mggqzm842xfr0v72rswzq9xvr4hknf" + + "sqwmn6xd", + + valid: true, + decodedInvoice: func() *Invoice { + return &Invoice{ + Net: &chaincfg.MainNetParams, + MilliSat: &testMillisat20mBTC, + Timestamp: time.Unix(1496314658, 0), + PaymentHash: &testPaymentHash, + DescriptionHash: &testDescriptionHash, + Destination: testPubKey, + FallbackAddr: testAddrMainnetP2TR, + Features: lnwire.NewFeatureVector( + lnwire.NewRawFeatureVector( + 8, 14, + ), + lnwire.Features, + ), + PaymentAddr: fn.Some(specPaymentAddr), + } + }, + // Skip encoding since LND encode the tagged fields + // in a different order. + skipEncoding: true, + }, { // Send 2500uBTC for a cup of coffee with a custom CLTV // expiry value.