commit a3cd33fe0364b326365b86f62424a212d03e87d0
parent 9be94c74d25e6ae4dc4956e4bf506d8f31e7280d
Author: ThomasV <thomasv@gitorious>
Date: Sun, 31 May 2015 16:43:27 +0200
add option to disable dnssec
Diffstat:
3 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/lib/commands.py b/lib/commands.py
@@ -65,7 +65,7 @@ register_command('decodetx', 0, 0, 0, ['tx'], [], 'Decode serialized t
register_command('getprivatekeys', 0, 1, 1, ['address'], [], 'Get the private keys of an address', 'Address must be in wallet.')
register_command('dumpprivkeys', 0, 1, 1, [], [], 'Dump private keys from your wallet', '')
register_command('freeze', 0, 1, 0, ['address'], [], 'Freeze address', 'Freeze the funds at one of your wallet\'s addresses')
-register_command('getalias', 0, 0, 0, ['key'], [], 'Retrieve alias', 'Lookup in your list of contacts, and for an OpenAlias DNS record')
+register_command('getalias', 0, 0, 0, ['key'], ['nocheck'], 'Retrieve alias', 'Lookup in your list of contacts, and for an OpenAlias DNS record')
register_command('getbalance', 1, 1, 0, [], [], 'Return the balance of your wallet', '')
register_command('getservers', 1, 0, 0, [], [], 'Return the list of available servers', '')
register_command('getaddressbalance', 1, 0, 0, ['address'], [], 'Return the balance of an address', '')
@@ -83,10 +83,10 @@ register_command('listaddresses', 0, 1, 0, [], ['show_all', 'show_labels',
'List wallet addresses', 'Returns your list of addresses.')
register_command('listunspent', 1, 1, 0, [], [], 'List unspent outputs', 'Returns the list of unspent transaction outputs in your wallet.')
register_command('getaddressunspent', 1, 0, 0, ['address'], [], 'Returns the list of unspent inputs for an address', '')
-register_command('mktx', 0, 1, 1, ['address', 'amount'], ['tx_fee', 'from_addr', 'change_addr'], 'Create signed transaction', '')
-register_command('payto', 1, 1, 1, ['address', 'amount'], ['tx_fee', 'from_addr', 'change_addr'], 'Create and broadcast a transaction.', '')
-register_command('mktx_csv', 0, 1, 1, ['csv_file'], ['tx_fee', 'from_addr', 'change_addr'], 'Create a signed transaction', '')
-register_command('payto_csv', 1, 1, 1, ['csv_file'], ['tx_fee', 'from_addr', 'change_addr'], 'Create and broadcast a transaction.', '')
+register_command('mktx', 0, 1, 1, ['address', 'amount'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck'], 'Create signed transaction', '')
+register_command('payto', 1, 1, 1, ['address', 'amount'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck'], 'Create and broadcast a transaction.', '')
+register_command('mktx_csv', 0, 1, 1, ['csv_file'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck'], 'Create a signed transaction', '')
+register_command('payto_csv', 1, 1, 1, ['csv_file'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck'], 'Create and broadcast a transaction.', '')
register_command('password', 0, 1, 1, [], [], 'Change your password', '')
register_command('restore', 1, 1, 0, [], ['gap_limit', 'mpk', 'concealed'], 'Restore a wallet from seed', '')
register_command('searchcontacts', 0, 1, 0, ['query'], [], 'Search through contacts, return matching entries', '')
@@ -137,6 +137,7 @@ command_options = {
'funded': (None, "--funded", False, "Show only funded addresses"),
'show_balance':("-b", "--balance", False, "Show the balances of listed addresses"),
'show_labels': ("-l", "--labels", False, "Show the labels of listed addresses"),
+ 'nocheck': (None, "--nocheck", False, "Do not verify aliases"),
'tx_fee': ("-f", "--fee", None, "Transaction fee (in BTC)"),
'from_addr': ("-F", "--from", None, "Source address. If it isn't in the wallet, it will ask for the private key unless supplied in the format public_key:private_key. It's not saved in the wallet."),
'change_addr': ("-c", "--change", None, "Change address. Default is a spare address, or the source address if it's not in the wallet"),
@@ -427,13 +428,14 @@ class Commands:
def verifymessage(self, address, signature, message):
return bitcoin.verify_message(address, signature, message)
- def _mktx(self, outputs, fee=None, change_addr=None, domain=None):
- change_addr = None if change_addr is None else self.contacts.resolve(change_addr)
- domain = None if domain is None else map(self.contacts.resolve, domain)
+ def _mktx(self, outputs, fee=None, change_addr=None, domain=None, nocheck=False):
+ resolver = lambda x: None if x is None else self.contacts.resolve(x, nocheck)['address']
+ change_addr = resolver(change_addr)
+ domain = None if domain is None else map(resolver, domain)
fee = None if fee is None else int(100000000*Decimal(fee))
final_outputs = []
for address, amount in outputs:
- address = self.contacts.resolve(address)
+ address = resolver(address)
#assert self.wallet.is_mine(address)
if amount == '!':
assert len(outputs) == 1
@@ -464,28 +466,28 @@ class Commands:
outputs.append((address, amount))
return outputs
- def mktx(self, to_address, amount, fee=None, from_addr=None, change_addr=None):
+ def mktx(self, to_address, amount, fee=None, from_addr=None, change_addr=None, nocheck=False):
domain = [from_addr] if from_addr else None
- tx = self._mktx([(to_address, amount)], fee, change_addr, domain)
+ tx = self._mktx([(to_address, amount)], fee, change_addr, domain, nocheck)
return tx
- def mktx_csv(self, path, fee=None, from_addr=None, change_addr=None):
+ def mktx_csv(self, path, fee=None, from_addr=None, change_addr=None, nocheck=False):
domain = [from_addr] if from_addr else None
outputs = self._read_csv(path)
- tx = self._mktx(outputs, fee, change_addr, domain)
+ tx = self._mktx(outputs, fee, change_addr, domain, nocheck)
return tx
- def payto(self, to_address, amount, fee=None, from_addr=None, change_addr=None):
+ def payto(self, to_address, amount, fee=None, from_addr=None, change_addr=None, nocheck=False):
domain = [from_addr] if from_addr else None
- tx = self._mktx([(to_address, amount)], fee, change_addr, domain)
- r, h = self.wallet.sendtx( tx )
+ tx = self._mktx([(to_address, amount)], fee, change_addr, domain, nocheck)
+ r, h = self.wallet.sendtx(tx)
return h
- def payto_csv(self, path, fee = None, from_addr=None, change_addr=None):
+ def payto_csv(self, path, fee = None, from_addr=None, change_addr=None, nocheck=False):
domain = [from_addr] if from_addr else None
outputs = self._read_csv(path)
- tx = self._mktx(outputs, fee, change_addr, domain)
- r, h = self.wallet.sendtx( tx )
+ tx = self._mktx(outputs, fee, change_addr, domain, nocheck)
+ r, h = self.wallet.sendtx(tx)
return h
def history(self):
@@ -509,8 +511,8 @@ class Commands:
def listcontacts(self):
return self.contacts
- def getalias(self, key):
- return self.contacts.resolve(key)
+ def getalias(self, key, nocheck=False):
+ return self.contacts.resolve(key, nocheck)
def searchcontacts(self, query):
results = {}
diff --git a/lib/util.py b/lib/util.py
@@ -467,18 +467,20 @@ import bitcoin
from plugins import run_hook
class Contacts(StoreDict):
+
def __init__(self, config):
StoreDict.__init__(self, config, 'contacts')
- def resolve(self, k):
+ def resolve(self, k, nocheck=False):
if bitcoin.is_address(k):
- return k
+ return {'address':k, 'type':'address'}
if k in self.keys():
_type, addr = self[k]
if _type == 'address':
- return addr
+ return {'address':addr, 'type':'contact'}
out = run_hook('resolve_address', k)
if out:
+ if not nocheck and out.get('validated') is False:
+ raise Exception("cannot validate alias")
return out
raise Exception("invalid Bitcoin address", k)
-
diff --git a/plugins/openalias.py b/plugins/openalias.py
@@ -181,7 +181,22 @@ class Plugin(BasePlugin):
@hook
def resolve_address(self, url):
- return self.resolve(url)[0]
+ data = self.resolve(url)
+ if not data:
+ return
+ address, name = data
+ try:
+ validated = self.validate_dnssec(url)
+ except:
+ validated = False
+ traceback.print_exc(file=sys.stderr)
+ return {
+ 'address': address,
+ 'name': name,
+ 'type': 'openalias',
+ 'validated': validated
+ }
+
def resolve(self, url):
'''Resolve OpenAlias address using url.'''
@@ -244,7 +259,7 @@ class Plugin(BasePlugin):
response = dns.query.udp(query, ns, 3)
if response.rcode() != dns.rcode.NOERROR:
self.print_error("query error")
- return 0
+ return False
if len(response.authority) > 0:
rrset = response.authority[0]
@@ -262,14 +277,14 @@ class Plugin(BasePlugin):
response = dns.query.udp(query, ns, 3)
if response.rcode() != 0:
self.print_error("query error")
- return 0
+ return False
# HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD)
# answer should contain two RRSET: DNSKEY and RRSIG(DNSKEY)
answer = response.answer
if len(answer) != 2:
self.print_error("answer error", answer)
- return 0
+ return False
# the DNSKEY should be self signed, validate it
name = dns.name.from_text(sub)
@@ -277,6 +292,6 @@ class Plugin(BasePlugin):
dns.dnssec.validate(answer[0], answer[1], {name: answer[0]})
except dns.dnssec.ValidationFailure:
self.print_error("validation error")
- return 0
+ return False
- return 1
+ return True