/ zpay32 / fuzz_test.go
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  }