fuzz_test.go
1 package zpay32 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/btcsuite/btcd/chaincfg" 8 ) 9 10 // getPrefixAndChainParams selects network chain parameters based on the fuzzer- 11 // selected input byte "net". 50% of the time mainnet is selected, while the 12 // other 50% of the time one of the test networks is selected. For each network 13 // the appropriate invoice HRP prefix is also returned, with a small chance that 14 // no prefix is returned, allowing the fuzzer to generate invalid prefixes too. 15 func getPrefixAndChainParams(net byte) (string, *chaincfg.Params) { 16 switch { 17 case net == 0x00: 18 return "", &chaincfg.RegressionNetParams 19 case net < 0x20: 20 return "lnbcrt", &chaincfg.RegressionNetParams 21 22 case net == 0x20: 23 return "", &chaincfg.TestNet3Params 24 case net < 0x40: 25 return "lntb", &chaincfg.TestNet3Params 26 27 case net == 0x40: 28 return "", &chaincfg.SimNetParams 29 case net < 0x60: 30 return "lnsb", &chaincfg.SimNetParams 31 32 case net == 0x60: 33 return "", &chaincfg.SigNetParams 34 case net < 0x80: 35 return "lntbs", &chaincfg.SigNetParams 36 37 case net == 0x80: 38 return "", &chaincfg.MainNetParams 39 default: 40 return "lnbc", &chaincfg.MainNetParams 41 } 42 } 43 44 func FuzzDecode(f *testing.F) { 45 f.Fuzz(func(t *testing.T, net byte, data string) { 46 _, chainParams := getPrefixAndChainParams(net) 47 _, _ = Decode(data, chainParams) 48 }) 49 } 50 51 // appendChecksum returns a string containing bech followed by its bech32 52 // checksum if a checksum could be calculated. Otherwise, the function returns 53 // bech unchanged. 54 // 55 // This code is based on checksum calculation in zpay32/bech32.go. 56 func appendChecksum(bech string) string { 57 lower := strings.ToLower(bech) 58 59 // The string is invalid if the last '1' is non-existent or it is the 60 // first character of the string (no human-readable part). 61 one := strings.LastIndexByte(lower, '1') 62 if one < 1 { 63 return bech 64 } 65 hrp := lower[:one] 66 data := lower[one+1:] 67 68 decoded, err := toBytes(data) 69 if err != nil { 70 return bech 71 } 72 73 checksum, err := toChars(bech32Checksum(hrp, decoded)) 74 if err != nil { 75 return bech 76 } 77 78 return bech + checksum 79 } 80 81 func FuzzEncode(f *testing.F) { 82 f.Fuzz(func(t *testing.T, net byte, data string) { 83 // Make it easier for the fuzzer to generate valid invoice 84 // encodings by adding the required prefix and valid checksum. 85 hrpPrefix, chainParams := getPrefixAndChainParams(net) 86 data = hrpPrefix + data 87 data = appendChecksum(data) 88 89 inv, err := Decode(data, chainParams) 90 if err != nil { 91 return 92 } 93 94 // Re-encode the invoice using our private key from unit tests. 95 _, err = inv.Encode(testMessageSigner) 96 if err != nil { 97 return 98 } 99 }) 100 }