zpay32: help fuzzer generate valid encodings

It is very difficult for the fuzzer to create a valid checksum for each
serialized invoice, and we were therefore unable to fuzz deeper than
invoice decoding. We can help the fuzzer generate valid serialized
invoices by calculating and appending the checksum ourselves.

We also switch to using mainnet invoices to make it easier to find valid
invoices for seeding the fuzzer. We prepend the required "lnbc" prefix
ourselves to further help the fuzzer generate valid invoices.
This commit is contained in:
Matt Morehouse 2023-05-23 10:19:50 -05:00
parent 82753f091b
commit bd7ec84497
No known key found for this signature in database
GPG key ID: CC8ECA224831C982

View file

@ -1,6 +1,7 @@
package zpay32
import (
"strings"
"testing"
"github.com/btcsuite/btcd/chaincfg"
@ -12,9 +13,44 @@ func FuzzDecode(f *testing.F) {
})
}
// appendChecksum returns a string containing bech followed by its bech32
// checksum if a checksum could be calculated. Otherwise, the function returns
// bech unchanged.
//
// This code is based on checksum calculation in zpay32/bech32.go.
func appendChecksum(bech string) string {
lower := strings.ToLower(bech)
// The string is invalid if the last '1' is non-existent or it is the
// first character of the string (no human-readable part).
one := strings.LastIndexByte(lower, '1')
if one < 1 {
return bech
}
hrp := lower[:one]
data := lower[one+1:]
decoded, err := toBytes(data)
if err != nil {
return bech
}
checksum, err := toChars(bech32Checksum(hrp, decoded))
if err != nil {
return bech
}
return bech + checksum
}
func FuzzEncode(f *testing.F) {
f.Fuzz(func(t *testing.T, data string) {
inv, err := Decode(data, &chaincfg.TestNet3Params)
// Make it easier for the fuzzer to generate valid invoice
// encodings by adding the required prefix and valid checksum.
data = "lnbc" + data
data = appendChecksum(data)
inv, err := Decode(data, &chaincfg.MainNetParams)
if err != nil {
return
}