add option to disable dnssec
This commit is contained in:
parent
9be94c74d2
commit
a3cd33fe03
|
@ -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('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('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('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('getbalance', 1, 1, 0, [], [], 'Return the balance of your wallet', '')
|
||||||
register_command('getservers', 1, 0, 0, [], [], 'Return the list of available servers', '')
|
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', '')
|
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.')
|
'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('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('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('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'], 'Create and broadcast a 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'], 'Create a signed 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'], 'Create and broadcast a 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('password', 0, 1, 1, [], [], 'Change your password', '')
|
||||||
register_command('restore', 1, 1, 0, [], ['gap_limit', 'mpk', 'concealed'], 'Restore a wallet from seed', '')
|
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', '')
|
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"),
|
'funded': (None, "--funded", False, "Show only funded addresses"),
|
||||||
'show_balance':("-b", "--balance", False, "Show the balances of listed addresses"),
|
'show_balance':("-b", "--balance", False, "Show the balances of listed addresses"),
|
||||||
'show_labels': ("-l", "--labels", False, "Show the labels 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)"),
|
'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."),
|
'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"),
|
'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):
|
def verifymessage(self, address, signature, message):
|
||||||
return bitcoin.verify_message(address, signature, message)
|
return bitcoin.verify_message(address, signature, message)
|
||||||
|
|
||||||
def _mktx(self, outputs, fee=None, change_addr=None, domain=None):
|
def _mktx(self, outputs, fee=None, change_addr=None, domain=None, nocheck=False):
|
||||||
change_addr = None if change_addr is None else self.contacts.resolve(change_addr)
|
resolver = lambda x: None if x is None else self.contacts.resolve(x, nocheck)['address']
|
||||||
domain = None if domain is None else map(self.contacts.resolve, domain)
|
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))
|
fee = None if fee is None else int(100000000*Decimal(fee))
|
||||||
final_outputs = []
|
final_outputs = []
|
||||||
for address, amount in outputs:
|
for address, amount in outputs:
|
||||||
address = self.contacts.resolve(address)
|
address = resolver(address)
|
||||||
#assert self.wallet.is_mine(address)
|
#assert self.wallet.is_mine(address)
|
||||||
if amount == '!':
|
if amount == '!':
|
||||||
assert len(outputs) == 1
|
assert len(outputs) == 1
|
||||||
|
@ -464,27 +466,27 @@ class Commands:
|
||||||
outputs.append((address, amount))
|
outputs.append((address, amount))
|
||||||
return outputs
|
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
|
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
|
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
|
domain = [from_addr] if from_addr else None
|
||||||
outputs = self._read_csv(path)
|
outputs = self._read_csv(path)
|
||||||
tx = self._mktx(outputs, fee, change_addr, domain)
|
tx = self._mktx(outputs, fee, change_addr, domain, nocheck)
|
||||||
return tx
|
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
|
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)
|
||||||
r, h = self.wallet.sendtx(tx)
|
r, h = self.wallet.sendtx(tx)
|
||||||
return h
|
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
|
domain = [from_addr] if from_addr else None
|
||||||
outputs = self._read_csv(path)
|
outputs = self._read_csv(path)
|
||||||
tx = self._mktx(outputs, fee, change_addr, domain)
|
tx = self._mktx(outputs, fee, change_addr, domain, nocheck)
|
||||||
r, h = self.wallet.sendtx(tx)
|
r, h = self.wallet.sendtx(tx)
|
||||||
return h
|
return h
|
||||||
|
|
||||||
|
@ -509,8 +511,8 @@ class Commands:
|
||||||
def listcontacts(self):
|
def listcontacts(self):
|
||||||
return self.contacts
|
return self.contacts
|
||||||
|
|
||||||
def getalias(self, key):
|
def getalias(self, key, nocheck=False):
|
||||||
return self.contacts.resolve(key)
|
return self.contacts.resolve(key, nocheck)
|
||||||
|
|
||||||
def searchcontacts(self, query):
|
def searchcontacts(self, query):
|
||||||
results = {}
|
results = {}
|
||||||
|
|
10
lib/util.py
10
lib/util.py
|
@ -467,18 +467,20 @@ import bitcoin
|
||||||
from plugins import run_hook
|
from plugins import run_hook
|
||||||
|
|
||||||
class Contacts(StoreDict):
|
class Contacts(StoreDict):
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
StoreDict.__init__(self, config, 'contacts')
|
StoreDict.__init__(self, config, 'contacts')
|
||||||
|
|
||||||
def resolve(self, k):
|
def resolve(self, k, nocheck=False):
|
||||||
if bitcoin.is_address(k):
|
if bitcoin.is_address(k):
|
||||||
return k
|
return {'address':k, 'type':'address'}
|
||||||
if k in self.keys():
|
if k in self.keys():
|
||||||
_type, addr = self[k]
|
_type, addr = self[k]
|
||||||
if _type == 'address':
|
if _type == 'address':
|
||||||
return addr
|
return {'address':addr, 'type':'contact'}
|
||||||
out = run_hook('resolve_address', k)
|
out = run_hook('resolve_address', k)
|
||||||
if out:
|
if out:
|
||||||
|
if not nocheck and out.get('validated') is False:
|
||||||
|
raise Exception("cannot validate alias")
|
||||||
return out
|
return out
|
||||||
raise Exception("invalid Bitcoin address", k)
|
raise Exception("invalid Bitcoin address", k)
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,22 @@ class Plugin(BasePlugin):
|
||||||
|
|
||||||
@hook
|
@hook
|
||||||
def resolve_address(self, url):
|
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):
|
def resolve(self, url):
|
||||||
'''Resolve OpenAlias address using url.'''
|
'''Resolve OpenAlias address using url.'''
|
||||||
|
@ -244,7 +259,7 @@ class Plugin(BasePlugin):
|
||||||
response = dns.query.udp(query, ns, 3)
|
response = dns.query.udp(query, ns, 3)
|
||||||
if response.rcode() != dns.rcode.NOERROR:
|
if response.rcode() != dns.rcode.NOERROR:
|
||||||
self.print_error("query error")
|
self.print_error("query error")
|
||||||
return 0
|
return False
|
||||||
|
|
||||||
if len(response.authority) > 0:
|
if len(response.authority) > 0:
|
||||||
rrset = response.authority[0]
|
rrset = response.authority[0]
|
||||||
|
@ -262,14 +277,14 @@ class Plugin(BasePlugin):
|
||||||
response = dns.query.udp(query, ns, 3)
|
response = dns.query.udp(query, ns, 3)
|
||||||
if response.rcode() != 0:
|
if response.rcode() != 0:
|
||||||
self.print_error("query error")
|
self.print_error("query error")
|
||||||
return 0
|
return False
|
||||||
# HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD)
|
# HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD)
|
||||||
|
|
||||||
# answer should contain two RRSET: DNSKEY and RRSIG(DNSKEY)
|
# answer should contain two RRSET: DNSKEY and RRSIG(DNSKEY)
|
||||||
answer = response.answer
|
answer = response.answer
|
||||||
if len(answer) != 2:
|
if len(answer) != 2:
|
||||||
self.print_error("answer error", answer)
|
self.print_error("answer error", answer)
|
||||||
return 0
|
return False
|
||||||
|
|
||||||
# the DNSKEY should be self signed, validate it
|
# the DNSKEY should be self signed, validate it
|
||||||
name = dns.name.from_text(sub)
|
name = dns.name.from_text(sub)
|
||||||
|
@ -277,6 +292,6 @@ class Plugin(BasePlugin):
|
||||||
dns.dnssec.validate(answer[0], answer[1], {name: answer[0]})
|
dns.dnssec.validate(answer[0], answer[1], {name: answer[0]})
|
||||||
except dns.dnssec.ValidationFailure:
|
except dns.dnssec.ValidationFailure:
|
||||||
self.print_error("validation error")
|
self.print_error("validation error")
|
||||||
return 0
|
return False
|
||||||
|
|
||||||
return 1
|
return True
|
||||||
|
|
Loading…
Reference in New Issue