zpay32: handle segwit prefixes > 2 chars
This change fixes a bug when an invoice is decoded for a network whose bech32 segwit prefix is longer than 2 characters. The length of the Bech32HRPSegwit network parameter is used to determine where in the human-readable portion of the invoice the amount begins, rather than assuming it begins after the first four characters. Decode() now throws an error when the encoded invoice does not match the active network. Changes the minimum hrp length check to >= 3 instead of >= 4. Also removes a redundant "if ...; err != nil check" that was raising a warning in invoice.go.
This commit is contained in:
parent
8329a31fb0
commit
fdbdcf1560
@ -265,9 +265,9 @@ func NewInvoice(net *chaincfg.Params, paymentHash [32]byte,
|
|||||||
return invoice, nil
|
return invoice, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode parses the provided encoded invoice, and returns a decoded Invoice in
|
// Decode parses the provided encoded invoice and returns a decoded Invoice if
|
||||||
// case it is valid by BOLT-0011.
|
// it is valid by BOLT-0011 and matches the provided active network.
|
||||||
func Decode(invoice string) (*Invoice, error) {
|
func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
|
||||||
decodedInvoice := Invoice{}
|
decodedInvoice := Invoice{}
|
||||||
|
|
||||||
// Decode the invoice using the modified bech32 decoder.
|
// Decode the invoice using the modified bech32 decoder.
|
||||||
@ -276,9 +276,9 @@ func Decode(invoice string) (*Invoice, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We expect the human-readable part to at least have ln + two chars
|
// We expect the human-readable part to at least have ln + one char
|
||||||
// encoding the network.
|
// encoding the network.
|
||||||
if len(hrp) < 4 {
|
if len(hrp) < 3 {
|
||||||
return nil, fmt.Errorf("hrp too short")
|
return nil, fmt.Errorf("hrp too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,24 +288,17 @@ func Decode(invoice string) (*Invoice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The next characters should be a valid prefix for a segwit BIP173
|
// The next characters should be a valid prefix for a segwit BIP173
|
||||||
// address. This will also determine which network this invoice is
|
// address that match the active network.
|
||||||
// meant for.
|
if !strings.HasPrefix(hrp[2:], net.Bech32HRPSegwit) {
|
||||||
var net *chaincfg.Params
|
|
||||||
if strings.HasPrefix(hrp[2:], chaincfg.MainNetParams.Bech32HRPSegwit) {
|
|
||||||
net = &chaincfg.MainNetParams
|
|
||||||
} else if strings.HasPrefix(hrp[2:], chaincfg.TestNet3Params.Bech32HRPSegwit) {
|
|
||||||
net = &chaincfg.TestNet3Params
|
|
||||||
} else if strings.HasPrefix(hrp[2:], chaincfg.SimNetParams.Bech32HRPSegwit) {
|
|
||||||
net = &chaincfg.SimNetParams
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("unknown network")
|
return nil, fmt.Errorf("unknown network")
|
||||||
}
|
}
|
||||||
decodedInvoice.Net = net
|
decodedInvoice.Net = net
|
||||||
|
|
||||||
// Optionally, if there's anything left of the HRP, it encodes the
|
// Optionally, if there's anything left of the HRP after ln + the segwit
|
||||||
// payment amount.
|
// prefix, we try to decode this as the payment amount.
|
||||||
if len(hrp) > 4 {
|
var netPrefixLength = len(net.Bech32HRPSegwit) + 2
|
||||||
amount, err := decodeAmount(hrp[4:])
|
if len(hrp) > netPrefixLength {
|
||||||
|
amount, err := decodeAmount(hrp[netPrefixLength:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -573,11 +566,7 @@ func parseData(invoice *Invoice, data []byte, net *chaincfg.Params) error {
|
|||||||
|
|
||||||
// The rest are tagged parts.
|
// The rest are tagged parts.
|
||||||
tagData := data[7:]
|
tagData := data[7:]
|
||||||
if err := parseTaggedFields(invoice, tagData, net); err != nil {
|
return parseTaggedFields(invoice, tagData, net)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseTimestamp converts a 35-bit timestamp (encoded in base32) to uint64.
|
// parseTimestamp converts a 35-bit timestamp (encoded in base32) to uint64.
|
||||||
|
Loading…
Reference in New Issue
Block a user