1
0

qt: fix: bip70 pay reqs need x509 verification

regression from https://github.com/spesmilo/electrum/pull/8462

- pr.verify() was called in qml, but not in qt gui
- we now call pr.verify() in get_payment_request(), to make the API less error-prone
- it is now ok to call pr.verify() multiple times, the result is cached
This commit is contained in:
SomberNight
2023-07-10 17:50:53 +00:00
parent 023e8ff0eb
commit 612a8e6424
6 changed files with 49 additions and 26 deletions

View File

@@ -21,7 +21,7 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import re
from typing import Optional, Tuple
from typing import Optional, Tuple, Dict, Any
import dns
import threading
@@ -30,10 +30,13 @@ from dns.exception import DNSException
from . import bitcoin
from . import dnssec
from .util import read_json_file, write_json_file, to_string
from .logging import Logger
from .logging import Logger, get_logger
from .util import trigger_callback
_logger = get_logger(__name__)
class AliasNotFoundException(Exception):
pass
@@ -90,7 +93,13 @@ class Contacts(dict, Logger):
'address': addr,
'type': 'contact'
}
out = self.resolve_openalias(k)
if openalias := self.resolve_openalias(k):
return openalias
raise AliasNotFoundException("Invalid Bitcoin address or alias", k)
@classmethod
def resolve_openalias(cls, url: str) -> Dict[str, Any]:
out = cls._resolve_openalias(url)
if out:
address, name, validated = out
return {
@@ -99,7 +108,7 @@ class Contacts(dict, Logger):
'type': 'openalias',
'validated': validated
}
raise AliasNotFoundException("Invalid Bitcoin address or alias", k)
return {}
def by_name(self, name):
for k in self.keys():
@@ -118,33 +127,35 @@ class Contacts(dict, Logger):
if alias:
alias = str(alias)
def f():
self.alias_info = self.resolve_openalias(alias)
self.alias_info = self._resolve_openalias(alias)
trigger_callback('alias_received')
t = threading.Thread(target=f)
t.daemon = True
t.start()
def resolve_openalias(self, url: str) -> Optional[Tuple[str, str, bool]]:
@classmethod
def _resolve_openalias(cls, url: str) -> Optional[Tuple[str, str, bool]]:
# support email-style addresses, per the OA standard
url = url.replace('@', '.')
try:
records, validated = dnssec.query(url, dns.rdatatype.TXT)
except DNSException as e:
self.logger.info(f'Error resolving openalias: {repr(e)}')
_logger.info(f'Error resolving openalias: {repr(e)}')
return None
prefix = 'btc'
for record in records:
string = to_string(record.strings[0], 'utf8')
if string.startswith('oa1:' + prefix):
address = self.find_regex(string, r'recipient_address=([A-Za-z0-9]+)')
name = self.find_regex(string, r'recipient_name=([^;]+)')
address = cls.find_regex(string, r'recipient_address=([A-Za-z0-9]+)')
name = cls.find_regex(string, r'recipient_name=([^;]+)')
if not name:
name = address
if not address:
continue
return address, name, validated
def find_regex(self, haystack, needle):
@staticmethod
def find_regex(haystack, needle):
regex = re.compile(needle)
try:
return regex.search(haystack).groups()[0]