check for descr hash

This commit is contained in:
callebtc 2022-08-14 21:50:14 +02:00
parent 042ccaf8ef
commit d7dc6f71aa
4 changed files with 68 additions and 24 deletions

View file

@ -229,7 +229,7 @@ func (w Lnurl) serveLNURLpSecond(username string, amount_msat int64, comment str
payerDataByte = []byte("")
}
descriptionHash, err := w.descriptionHash(metadata, string(payerDataByte))
descriptionHash, err := w.DescriptionHash(metadata, string(payerDataByte))
if err != nil {
return nil, err
}
@ -281,8 +281,8 @@ func (w Lnurl) serveLNURLpSecond(username string, amount_msat int64, comment str
}
// descriptionHash is the SHA256 hash of the metadata
func (w Lnurl) descriptionHash(metadata lnurl.Metadata, payerData string) (string, error) {
// DescriptionHash is the SHA256 hash of the metadata
func (w Lnurl) DescriptionHash(metadata lnurl.Metadata, payerData string) (string, error) {
var hashString string
var hash [32]byte
if len(payerData) == 0 {

View file

@ -1,6 +1,7 @@
package telegram
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
@ -19,27 +20,29 @@ import (
"github.com/LightningTipBot/LightningTipBot/internal/runtime"
lnurl "github.com/fiatjaf/go-lnurl"
decodepay "github.com/fiatjaf/ln-decodepay"
log "github.com/sirupsen/logrus"
)
// LnurlPayState saves the state of the user for an LNURL payment
type LnurlPayState struct {
*storage.Base
From *lnbits.User `json:"from"`
LNURLPayParams lnurl.LNURLPayParams `json:"LNURLPayParams"`
LNURLPayValues lnurl.LNURLPayValues `json:"LNURLPayValues"`
Amount int64 `json:"amount"`
Comment string `json:"comment"`
LanguageCode string `json:"languagecode"`
From *lnbits.User `json:"from"`
LNURLPayParams lnurl.LNURLPayParams `json:"LNURLPayParams"`
LNURLPayValues lnurl.LNURLPayValues `json:"LNURLPayValues"`
Amount int64 `json:"amount"`
Comment string `json:"comment"`
DescriptionHash string `json:"descriptionHash,omitempty"`
LanguageCode string `json:"languagecode"`
}
// lnurlPayHandler1 is invoked when the first lnurl response was a lnurlpay response
// lnurlPayHandler is invoked when the first lnurl response was a lnurlpay response
// at this point, the user hans't necessarily entered an amount yet
func (bot *TipBot) lnurlPayHandler(ctx intercept.Context, payParams *LnurlPayState) {
func (bot *TipBot) lnurlPayHandler(ctx intercept.Context, payParams *LnurlPayState) (context.Context, error) {
m := ctx.Message()
user := LoadUser(ctx)
if user.Wallet == nil {
return
return ctx, fmt.Errorf("user has no wallet")
}
// object that holds all information about the send payment
id := fmt.Sprintf("lnurlp-%d-%s", m.Sender.ID, RandStringRunes(5))
@ -76,11 +79,18 @@ func (bot *TipBot) lnurlPayHandler(ctx intercept.Context, payParams *LnurlPaySta
log.Warnf("[lnurlPayHandler] Error: %s", err.Error())
bot.trySendMessage(m.Sender, fmt.Sprintf(Translate(ctx, "lnurlInvalidAmountRangeMessage"), payParams.LNURLPayParams.MinSendable/1000, payParams.LNURLPayParams.MaxSendable/1000))
ResetUserState(user, bot)
return
return ctx, err
}
// set also amount in the state of the user
payParams.Amount = amount * 1000 // save as mSat
// calculate description hash of the metadata and save it
descriptionHash, err := bot.DescriptionHash(payParams.LNURLPayParams.Metadata, "")
if err != nil {
return nil, err
}
payParams.DescriptionHash = descriptionHash
// add result to persistent struct
runtime.IgnoreError(payParams.Set(payParams, bot.Bunt))
@ -91,7 +101,7 @@ func (bot *TipBot) lnurlPayHandler(ctx intercept.Context, payParams *LnurlPaySta
} else if amount_err != nil || amount < 1 {
// // no amount was entered, set user state and ask for amount
bot.askForAmount(ctx, id, "LnurlPayState", payParams.LNURLPayParams.MinSendable, payParams.LNURLPayParams.MaxSendable, m.Text)
return
return ctx, nil
}
// We need to save the pay state in the user state so we can load the payment in the next ctx
@ -99,12 +109,12 @@ func (bot *TipBot) lnurlPayHandler(ctx intercept.Context, payParams *LnurlPaySta
if err != nil {
log.Errorf("[lnurlPayHandler] Error: %s", err.Error())
// bot.trySendMessage(m.Sender, err.Error())
return
return ctx, err
}
SetUserState(user, bot, lnbits.UserHasEnteredAmount, string(paramsJson))
// directly go to confirm
bot.lnurlPayHandlerSend(ctx)
return
return ctx, nil
}
// lnurlPayHandlerSend is invoked when the user has delivered an amount and is ready to pay
@ -187,11 +197,28 @@ func (bot *TipBot) lnurlPayHandlerSend(ctx intercept.Context) (intercept.Context
if len(response2.Reason) > 0 {
error_reason = response2.Reason
}
log.Errorf("[lnurlPayHandler] Error in LNURLPayValues: %s", error_reason)
log.Errorf("[lnurlPayHandlerSend] Error in LNURLPayValues: %s", error_reason)
bot.tryEditMessage(statusMsg, fmt.Sprintf(Translate(ctx, "lnurlPaymentFailed"), error_reason))
return ctx, fmt.Errorf("Error in LNURLPayValues: %s", error_reason)
return ctx, fmt.Errorf("error in LNURLPayValues: %s", error_reason)
}
// check whether description hash matches with expected hash
// decode invoice
bolt11, err := decodepay.Decodepay(response2.PR)
if err != nil {
bot.trySendMessage(ctx.Sender(), helpPayInvoiceUsage(ctx, Translate(ctx, "invalidInvoiceHelpMessage")))
errmsg := fmt.Sprintf("[/pay] Error: Could not decode invoice: %s", err.Error())
log.Errorln(errmsg)
return ctx, errors.New(errors.InvalidSyntaxError, err)
}
if bolt11.DescriptionHash != lnurlPayState.DescriptionHash {
log.Errorf("[lnurlPayHandlerSend] Error: description hash doesn't match")
bot.tryEditMessage(statusMsg, fmt.Sprintf(Translate(ctx, "errorReasonMessage"), "description hash doesn't match.\nExpected: `"+lnurlPayState.DescriptionHash+"` Received: `"+bolt11.DescriptionHash+"`"))
return ctx, fmt.Errorf("description hash doesn't match")
}
// all good
lnurlPayState.LNURLPayValues = response2
// add result to persistent struct
runtime.IgnoreError(lnurlPayState.Set(lnurlPayState, bot.Bunt))

View file

@ -2,6 +2,8 @@ package telegram
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
"net/url"
@ -22,7 +24,7 @@ import (
tb "gopkg.in/lightningtipbot/telebot.v3"
)
func (bot TipBot) cancelLnUrlHandler(c *tb.Callback) {
func (bot *TipBot) cancelLnUrlHandler(c *tb.Callback) {
}
// lnurlHandler is invoked on /lnurl command
@ -151,7 +153,7 @@ func UserGetAnonLNURL(user *lnbits.User) (string, error) {
}
// lnurlReceiveHandler outputs the LNURL of the user
func (bot TipBot) lnurlReceiveHandler(ctx intercept.Context) (intercept.Context, error) {
func (bot *TipBot) lnurlReceiveHandler(ctx intercept.Context) (intercept.Context, error) {
m := ctx.Message()
fromUser := LoadUser(ctx)
lnurlEncode, err := UserGetLNURL(fromUser)
@ -176,7 +178,7 @@ func (bot TipBot) lnurlReceiveHandler(ctx intercept.Context) (intercept.Context,
}
// fiatjaf/go-lnurl 1.8.4 with proxy
func (bot TipBot) HandleLNURL(rawlnurl string) (string, lnurl.LNURLParams, error) {
func (bot *TipBot) HandleLNURL(rawlnurl string) (string, lnurl.LNURLParams, error) {
var err error
var rawurl string
@ -276,3 +278,17 @@ func (bot TipBot) HandleLNURL(rawlnurl string) (string, lnurl.LNURLParams, error
return rawurl, nil, fmt.Errorf("Unkown LNURL response.")
}
}
// DescriptionHash is the SHA256 hash of the metadata
func (bot *TipBot) DescriptionHash(metadata lnurl.Metadata, payerData string) (string, error) {
var hashString string
var hash [32]byte
if len(payerData) == 0 {
hash = sha256.Sum256([]byte(metadata.Encode()))
hashString = hex.EncodeToString(hash[:])
} else {
hash = sha256.Sum256([]byte(metadata.Encode() + payerData))
hashString = hex.EncodeToString(hash[:])
}
return hashString, nil
}

View file

@ -127,9 +127,10 @@ advancedMessage = """%s
*/shop* 🛍 Durchsuche shops: `/shop` oder `/shop <user/shop_id>`"""
# GENERIC
enterAmountRangeMessage = """⌨️ Gebe einen Betrag zwischen %d und %d sat ein."""
enterAmountMessage = """⌨️ Gebe einen Betrag ein."""
errorReasonMessage = """🚫 Fehler: %s"""
enterAmountRangeMessage = """💯 Gebe Betrag zwuschen %d und %d sat ein."""
enterAmountMessage = """💯 Gebe Betrag ein."""
enterUserMessage = """👤 Gebe Benutzernamen ein."""
errorReasonMessage = """🚫 Fehler: %s"""
# START